xref: /onnv-gate/usr/src/uts/common/io/hxge/hxge_main.c (revision 11878:ac93462db6d7)
16349Sqs148142 /*
26349Sqs148142  * CDDL HEADER START
36349Sqs148142  *
46349Sqs148142  * The contents of this file are subject to the terms of the
56349Sqs148142  * Common Development and Distribution License (the "License").
66349Sqs148142  * You may not use this file except in compliance with the License.
76349Sqs148142  *
86349Sqs148142  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96349Sqs148142  * or http://www.opensolaris.org/os/licensing.
106349Sqs148142  * See the License for the specific language governing permissions
116349Sqs148142  * and limitations under the License.
126349Sqs148142  *
136349Sqs148142  * When distributing Covered Code, include this CDDL HEADER in each
146349Sqs148142  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156349Sqs148142  * If applicable, add the following below this CDDL HEADER, with the
166349Sqs148142  * fields enclosed by brackets "[]" replaced with your own identifying
176349Sqs148142  * information: Portions Copyright [yyyy] [name of copyright owner]
186349Sqs148142  *
196349Sqs148142  * CDDL HEADER END
206349Sqs148142  */
216349Sqs148142 /*
22*11878SVenu.Iyer@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
236349Sqs148142  * Use is subject to license terms.
246349Sqs148142  */
256349Sqs148142 
266349Sqs148142 /*
276349Sqs148142  * SunOs MT STREAMS Hydra 10Gb Ethernet Device Driver.
286349Sqs148142  */
296349Sqs148142 #include <hxge_impl.h>
306349Sqs148142 #include <hxge_pfc.h>
316349Sqs148142 
326349Sqs148142 /*
336349Sqs148142  * PSARC/2007/453 MSI-X interrupt limit override
346349Sqs148142  * (This PSARC case is limited to MSI-X vectors
356349Sqs148142  *  and SPARC platforms only).
366349Sqs148142  */
376349Sqs148142 uint32_t hxge_msi_enable = 2;
386349Sqs148142 
396349Sqs148142 /*
406349Sqs148142  * Globals: tunable parameters (/etc/system or adb)
416349Sqs148142  *
426349Sqs148142  */
436349Sqs148142 uint32_t hxge_rbr_size = HXGE_RBR_RBB_DEFAULT;
446349Sqs148142 uint32_t hxge_rbr_spare_size = 0;
456349Sqs148142 uint32_t hxge_rcr_size = HXGE_RCR_DEFAULT;
466349Sqs148142 uint32_t hxge_tx_ring_size = HXGE_TX_RING_DEFAULT;
476349Sqs148142 uint32_t hxge_bcopy_thresh = TX_BCOPY_MAX;
486349Sqs148142 uint32_t hxge_dvma_thresh = TX_FASTDVMA_MIN;
496349Sqs148142 uint32_t hxge_dma_stream_thresh = TX_STREAM_MIN;
507584SQiyan.Sun@Sun.COM uint32_t hxge_jumbo_frame_size = MAX_FRAME_SIZE;
516349Sqs148142 
526349Sqs148142 static hxge_os_mutex_t hxgedebuglock;
536349Sqs148142 static int hxge_debug_init = 0;
546349Sqs148142 
556349Sqs148142 /*
566349Sqs148142  * Debugging flags:
576349Sqs148142  *		hxge_no_tx_lb : transmit load balancing
586349Sqs148142  *		hxge_tx_lb_policy: 0 - TCP/UDP port (default)
596349Sqs148142  *				   1 - From the Stack
606349Sqs148142  *				   2 - Destination IP Address
616349Sqs148142  */
626349Sqs148142 uint32_t hxge_no_tx_lb = 0;
636349Sqs148142 uint32_t hxge_tx_lb_policy = HXGE_TX_LB_TCPUDP;
646349Sqs148142 
656349Sqs148142 /*
666349Sqs148142  * Tunables to manage the receive buffer blocks.
676349Sqs148142  *
686349Sqs148142  * hxge_rx_threshold_hi: copy all buffers.
696349Sqs148142  * hxge_rx_bcopy_size_type: receive buffer block size type.
706349Sqs148142  * hxge_rx_threshold_lo: copy only up to tunable block size type.
716349Sqs148142  */
7211257SMichael.Speer@Sun.COM #if defined(__sparc)
7311257SMichael.Speer@Sun.COM hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_6;
7411257SMichael.Speer@Sun.COM hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_4;
7511257SMichael.Speer@Sun.COM #else
768366SQiyan.Sun@Sun.COM hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_NONE;
7711257SMichael.Speer@Sun.COM hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_NONE;
7811257SMichael.Speer@Sun.COM #endif
796349Sqs148142 hxge_rxbuf_type_t hxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
806349Sqs148142 
816349Sqs148142 rtrace_t hpi_rtracebuf;
826349Sqs148142 
836349Sqs148142 /*
846349Sqs148142  * Function Prototypes
856349Sqs148142  */
866349Sqs148142 static int hxge_attach(dev_info_t *, ddi_attach_cmd_t);
876349Sqs148142 static int hxge_detach(dev_info_t *, ddi_detach_cmd_t);
886349Sqs148142 static void hxge_unattach(p_hxge_t);
896349Sqs148142 
906349Sqs148142 static hxge_status_t hxge_setup_system_dma_pages(p_hxge_t);
916349Sqs148142 
926349Sqs148142 static hxge_status_t hxge_setup_mutexes(p_hxge_t);
936349Sqs148142 static void hxge_destroy_mutexes(p_hxge_t);
946349Sqs148142 
956349Sqs148142 static hxge_status_t hxge_map_regs(p_hxge_t hxgep);
966349Sqs148142 static void hxge_unmap_regs(p_hxge_t hxgep);
976349Sqs148142 
9811257SMichael.Speer@Sun.COM static hxge_status_t hxge_add_intrs(p_hxge_t hxgep);
996349Sqs148142 static void hxge_remove_intrs(p_hxge_t hxgep);
1006349Sqs148142 static hxge_status_t hxge_add_intrs_adv(p_hxge_t hxgep);
1016349Sqs148142 static hxge_status_t hxge_add_intrs_adv_type(p_hxge_t, uint32_t);
1026349Sqs148142 static hxge_status_t hxge_add_intrs_adv_type_fix(p_hxge_t, uint32_t);
10311257SMichael.Speer@Sun.COM static void hxge_intrs_enable(p_hxge_t hxgep);
1046349Sqs148142 static void hxge_intrs_disable(p_hxge_t hxgep);
1056349Sqs148142 static void hxge_suspend(p_hxge_t);
1066349Sqs148142 static hxge_status_t hxge_resume(p_hxge_t);
10711257SMichael.Speer@Sun.COM static hxge_status_t hxge_setup_dev(p_hxge_t);
1086349Sqs148142 static void hxge_destroy_dev(p_hxge_t);
10911257SMichael.Speer@Sun.COM static hxge_status_t hxge_alloc_mem_pool(p_hxge_t);
1106349Sqs148142 static void hxge_free_mem_pool(p_hxge_t);
1116349Sqs148142 static hxge_status_t hxge_alloc_rx_mem_pool(p_hxge_t);
1126349Sqs148142 static void hxge_free_rx_mem_pool(p_hxge_t);
1136349Sqs148142 static hxge_status_t hxge_alloc_tx_mem_pool(p_hxge_t);
1146349Sqs148142 static void hxge_free_tx_mem_pool(p_hxge_t);
1156349Sqs148142 static hxge_status_t hxge_dma_mem_alloc(p_hxge_t, dma_method_t,
1166349Sqs148142     struct ddi_dma_attr *, size_t, ddi_device_acc_attr_t *, uint_t,
1176349Sqs148142     p_hxge_dma_common_t);
1186349Sqs148142 static void hxge_dma_mem_free(p_hxge_dma_common_t);
1196349Sqs148142 static hxge_status_t hxge_alloc_rx_buf_dma(p_hxge_t, uint16_t,
1206349Sqs148142     p_hxge_dma_common_t *, size_t, size_t, uint32_t *);
1216349Sqs148142 static void hxge_free_rx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t);
1226349Sqs148142 static hxge_status_t hxge_alloc_rx_cntl_dma(p_hxge_t, uint16_t,
1237618SMichael.Speer@Sun.COM     p_hxge_dma_common_t *, struct ddi_dma_attr *, size_t);
1246349Sqs148142 static void hxge_free_rx_cntl_dma(p_hxge_t, p_hxge_dma_common_t);
1256349Sqs148142 static hxge_status_t hxge_alloc_tx_buf_dma(p_hxge_t, uint16_t,
1266349Sqs148142     p_hxge_dma_common_t *, size_t, size_t, uint32_t *);
1276349Sqs148142 static void hxge_free_tx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t);
1286349Sqs148142 static hxge_status_t hxge_alloc_tx_cntl_dma(p_hxge_t, uint16_t,
1296349Sqs148142     p_hxge_dma_common_t *, size_t);
1306349Sqs148142 static void hxge_free_tx_cntl_dma(p_hxge_t, p_hxge_dma_common_t);
1316349Sqs148142 static int hxge_init_common_dev(p_hxge_t);
1326349Sqs148142 static void hxge_uninit_common_dev(p_hxge_t);
1336349Sqs148142 
1346349Sqs148142 /*
1356349Sqs148142  * The next declarations are for the GLDv3 interface.
1366349Sqs148142  */
1376349Sqs148142 static int hxge_m_start(void *);
1386349Sqs148142 static void hxge_m_stop(void *);
1396349Sqs148142 static int hxge_m_multicst(void *, boolean_t, const uint8_t *);
1406349Sqs148142 static int hxge_m_promisc(void *, boolean_t);
1416349Sqs148142 static void hxge_m_ioctl(void *, queue_t *, mblk_t *);
1426349Sqs148142 static hxge_status_t hxge_mac_register(p_hxge_t hxgep);
1436349Sqs148142 
1446349Sqs148142 static boolean_t hxge_m_getcapab(void *, mac_capab_t, void *);
1457584SQiyan.Sun@Sun.COM static boolean_t hxge_param_locked(mac_prop_id_t pr_num);
1467584SQiyan.Sun@Sun.COM static int hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
1477584SQiyan.Sun@Sun.COM     uint_t pr_valsize, const void *pr_val);
1487584SQiyan.Sun@Sun.COM static int hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
1497584SQiyan.Sun@Sun.COM     uint_t pr_valsize, void *pr_val);
150*11878SVenu.Iyer@Sun.COM static void hxge_m_propinfo(void *barg, const char *pr_name,
151*11878SVenu.Iyer@Sun.COM     mac_prop_id_t pr_num, mac_prop_info_handle_t mph);
1527584SQiyan.Sun@Sun.COM static int hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name,
1537584SQiyan.Sun@Sun.COM     uint_t pr_valsize, const void *pr_val);
1547584SQiyan.Sun@Sun.COM static int hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name,
155*11878SVenu.Iyer@Sun.COM     uint_t pr_valsize, void *pr_val);
1567584SQiyan.Sun@Sun.COM static void hxge_link_poll(void *arg);
1577949SQiyan.Sun@Sun.COM static void hxge_link_update(p_hxge_t hxge, link_state_t state);
1588236SQiyan.Sun@Sun.COM static void hxge_msix_init(p_hxge_t hxgep);
1597584SQiyan.Sun@Sun.COM 
160*11878SVenu.Iyer@Sun.COM char *hxge_priv_props[] = {
161*11878SVenu.Iyer@Sun.COM 	"_rxdma_intr_time",
162*11878SVenu.Iyer@Sun.COM 	"_rxdma_intr_pkts",
163*11878SVenu.Iyer@Sun.COM 	"_class_opt_ipv4_tcp",
164*11878SVenu.Iyer@Sun.COM 	"_class_opt_ipv4_udp",
165*11878SVenu.Iyer@Sun.COM 	"_class_opt_ipv4_ah",
166*11878SVenu.Iyer@Sun.COM 	"_class_opt_ipv4_sctp",
167*11878SVenu.Iyer@Sun.COM 	"_class_opt_ipv6_tcp",
168*11878SVenu.Iyer@Sun.COM 	"_class_opt_ipv6_udp",
169*11878SVenu.Iyer@Sun.COM 	"_class_opt_ipv6_ah",
170*11878SVenu.Iyer@Sun.COM 	"_class_opt_ipv6_sctp",
171*11878SVenu.Iyer@Sun.COM 	NULL
1727584SQiyan.Sun@Sun.COM };
1737584SQiyan.Sun@Sun.COM 
1747584SQiyan.Sun@Sun.COM #define	HXGE_MAX_PRIV_PROPS	\
1757584SQiyan.Sun@Sun.COM 	(sizeof (hxge_priv_props)/sizeof (mac_priv_prop_t))
1766349Sqs148142 
1776349Sqs148142 #define	HXGE_MAGIC	0x4E584745UL
1786349Sqs148142 #define	MAX_DUMP_SZ 256
1796349Sqs148142 
1807584SQiyan.Sun@Sun.COM #define	HXGE_M_CALLBACK_FLAGS	\
181*11878SVenu.Iyer@Sun.COM 	(MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
1826349Sqs148142 
1836349Sqs148142 extern hxge_status_t hxge_pfc_set_default_mac_addr(p_hxge_t hxgep);
1846349Sqs148142 
1856349Sqs148142 static mac_callbacks_t hxge_m_callbacks = {
1866349Sqs148142 	HXGE_M_CALLBACK_FLAGS,
1876349Sqs148142 	hxge_m_stat,
1886349Sqs148142 	hxge_m_start,
1896349Sqs148142 	hxge_m_stop,
1906349Sqs148142 	hxge_m_promisc,
1916349Sqs148142 	hxge_m_multicst,
1928718SMichael.Speer@Sun.COM 	NULL,
1938718SMichael.Speer@Sun.COM 	NULL,
194*11878SVenu.Iyer@Sun.COM 	NULL,
1956349Sqs148142 	hxge_m_ioctl,
1967584SQiyan.Sun@Sun.COM 	hxge_m_getcapab,
1977584SQiyan.Sun@Sun.COM 	NULL,
1987584SQiyan.Sun@Sun.COM 	NULL,
1997584SQiyan.Sun@Sun.COM 	hxge_m_setprop,
200*11878SVenu.Iyer@Sun.COM 	hxge_m_getprop,
201*11878SVenu.Iyer@Sun.COM 	hxge_m_propinfo
2026349Sqs148142 };
2036349Sqs148142 
2048366SQiyan.Sun@Sun.COM /* PSARC/2007/453 MSI-X interrupt limit override. */
2058366SQiyan.Sun@Sun.COM #define	HXGE_MSIX_REQUEST_10G	8
2068366SQiyan.Sun@Sun.COM static int hxge_create_msi_property(p_hxge_t);
2078366SQiyan.Sun@Sun.COM 
2086349Sqs148142 /* Enable debug messages as necessary. */
2097584SQiyan.Sun@Sun.COM uint64_t hxge_debug_level = 0;
2106349Sqs148142 
2116349Sqs148142 /*
2126349Sqs148142  * This list contains the instance structures for the Hydra
2136349Sqs148142  * devices present in the system. The lock exists to guarantee
2146349Sqs148142  * mutually exclusive access to the list.
2156349Sqs148142  */
2166349Sqs148142 void *hxge_list = NULL;
2176349Sqs148142 void *hxge_hw_list = NULL;
2186349Sqs148142 hxge_os_mutex_t hxge_common_lock;
2196349Sqs148142 
2206349Sqs148142 extern uint64_t hpi_debug_level;
2216349Sqs148142 
2226349Sqs148142 extern hxge_status_t hxge_ldgv_init();
2236349Sqs148142 extern hxge_status_t hxge_ldgv_uninit();
2246349Sqs148142 extern hxge_status_t hxge_intr_ldgv_init();
2256349Sqs148142 extern void hxge_fm_init(p_hxge_t hxgep, ddi_device_acc_attr_t *reg_attr,
22611257SMichael.Speer@Sun.COM     ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr);
2276349Sqs148142 extern void hxge_fm_fini(p_hxge_t hxgep);
2286349Sqs148142 
2296349Sqs148142 /*
2306349Sqs148142  * Count used to maintain the number of buffers being used
2316349Sqs148142  * by Hydra instances and loaned up to the upper layers.
2326349Sqs148142  */
2336349Sqs148142 uint32_t hxge_mblks_pending = 0;
2346349Sqs148142 
2356349Sqs148142 /*
2366349Sqs148142  * Device register access attributes for PIO.
2376349Sqs148142  */
2386349Sqs148142 static ddi_device_acc_attr_t hxge_dev_reg_acc_attr = {
23911257SMichael.Speer@Sun.COM 	DDI_DEVICE_ATTR_V0,
2406349Sqs148142 	DDI_STRUCTURE_LE_ACC,
2416349Sqs148142 	DDI_STRICTORDER_ACC,
2426349Sqs148142 };
2436349Sqs148142 
2446349Sqs148142 /*
2456349Sqs148142  * Device descriptor access attributes for DMA.
2466349Sqs148142  */
2476349Sqs148142 static ddi_device_acc_attr_t hxge_dev_desc_dma_acc_attr = {
2486349Sqs148142 	DDI_DEVICE_ATTR_V0,
2496349Sqs148142 	DDI_STRUCTURE_LE_ACC,
2506349Sqs148142 	DDI_STRICTORDER_ACC
2516349Sqs148142 };
2526349Sqs148142 
2536349Sqs148142 /*
2546349Sqs148142  * Device buffer access attributes for DMA.
2556349Sqs148142  */
2566349Sqs148142 static ddi_device_acc_attr_t hxge_dev_buf_dma_acc_attr = {
2576349Sqs148142 	DDI_DEVICE_ATTR_V0,
2586349Sqs148142 	DDI_STRUCTURE_BE_ACC,
2596349Sqs148142 	DDI_STRICTORDER_ACC
2606349Sqs148142 };
2616349Sqs148142 
2627618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_rx_rcr_desc_dma_attr = {
2637618SMichael.Speer@Sun.COM 	DMA_ATTR_V0,		/* version number. */
2647618SMichael.Speer@Sun.COM 	0,			/* low address */
2657618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* high address */
2667618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* address counter max */
2677618SMichael.Speer@Sun.COM 	0x80000,		/* alignment */
2687618SMichael.Speer@Sun.COM 	0xfc00fc,		/* dlim_burstsizes */
2697618SMichael.Speer@Sun.COM 	0x1,			/* minimum transfer size */
2707618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* maximum transfer size */
2717618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* maximum segment size */
2727618SMichael.Speer@Sun.COM 	1,			/* scatter/gather list length */
2737618SMichael.Speer@Sun.COM 	(unsigned int)1,	/* granularity */
2747618SMichael.Speer@Sun.COM 	0			/* attribute flags */
2757618SMichael.Speer@Sun.COM };
2767618SMichael.Speer@Sun.COM 
2777618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_tx_desc_dma_attr = {
2786349Sqs148142 	DMA_ATTR_V0,		/* version number. */
2796349Sqs148142 	0,			/* low address */
2806349Sqs148142 	0xffffffffffffffff,	/* high address */
2816349Sqs148142 	0xffffffffffffffff,	/* address counter max */
2826349Sqs148142 	0x100000,		/* alignment */
2836349Sqs148142 	0xfc00fc,		/* dlim_burstsizes */
2846349Sqs148142 	0x1,			/* minimum transfer size */
2856349Sqs148142 	0xffffffffffffffff,	/* maximum transfer size */
2866349Sqs148142 	0xffffffffffffffff,	/* maximum segment size */
2876349Sqs148142 	1,			/* scatter/gather list length */
2886349Sqs148142 	(unsigned int)1,	/* granularity */
2896349Sqs148142 	0			/* attribute flags */
2906349Sqs148142 };
2916349Sqs148142 
2927618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_rx_rbr_desc_dma_attr = {
2937618SMichael.Speer@Sun.COM 	DMA_ATTR_V0,		/* version number. */
2947618SMichael.Speer@Sun.COM 	0,			/* low address */
2957618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* high address */
2967618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* address counter max */
2977618SMichael.Speer@Sun.COM 	0x40000,		/* alignment */
2987618SMichael.Speer@Sun.COM 	0xfc00fc,		/* dlim_burstsizes */
2997618SMichael.Speer@Sun.COM 	0x1,			/* minimum transfer size */
3007618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* maximum transfer size */
3017618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* maximum segment size */
3027618SMichael.Speer@Sun.COM 	1,			/* scatter/gather list length */
3037618SMichael.Speer@Sun.COM 	(unsigned int)1,	/* granularity */
3047618SMichael.Speer@Sun.COM 	0			/* attribute flags */
3057618SMichael.Speer@Sun.COM };
3067618SMichael.Speer@Sun.COM 
3077618SMichael.Speer@Sun.COM ddi_dma_attr_t hxge_rx_mbox_dma_attr = {
3087618SMichael.Speer@Sun.COM 	DMA_ATTR_V0,		/* version number. */
3097618SMichael.Speer@Sun.COM 	0,			/* low address */
3107618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* high address */
3117618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* address counter max */
3127618SMichael.Speer@Sun.COM #if defined(_BIG_ENDIAN)
3137618SMichael.Speer@Sun.COM 	0x2000,			/* alignment */
3147618SMichael.Speer@Sun.COM #else
3157618SMichael.Speer@Sun.COM 	0x1000,			/* alignment */
3167618SMichael.Speer@Sun.COM #endif
3177618SMichael.Speer@Sun.COM 	0xfc00fc,		/* dlim_burstsizes */
3187618SMichael.Speer@Sun.COM 	0x1,			/* minimum transfer size */
3197618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* maximum transfer size */
3207618SMichael.Speer@Sun.COM 	0xffffffffffffffff,	/* maximum segment size */
3217618SMichael.Speer@Sun.COM 	5,			/* scatter/gather list length */
3227618SMichael.Speer@Sun.COM 	(unsigned int)1,	/* granularity */
3237618SMichael.Speer@Sun.COM 	0			/* attribute flags */
3247618SMichael.Speer@Sun.COM };
3257618SMichael.Speer@Sun.COM 
3266349Sqs148142 ddi_dma_attr_t hxge_tx_dma_attr = {
3276349Sqs148142 	DMA_ATTR_V0,		/* version number. */
3286349Sqs148142 	0,			/* low address */
3296349Sqs148142 	0xffffffffffffffff,	/* high address */
3306349Sqs148142 	0xffffffffffffffff,	/* address counter max */
3316349Sqs148142 #if defined(_BIG_ENDIAN)
3326349Sqs148142 	0x2000,			/* alignment */
3336349Sqs148142 #else
3346349Sqs148142 	0x1000,			/* alignment */
3356349Sqs148142 #endif
3366349Sqs148142 	0xfc00fc,		/* dlim_burstsizes */
3376349Sqs148142 	0x1,			/* minimum transfer size */
3386349Sqs148142 	0xffffffffffffffff,	/* maximum transfer size */
3396349Sqs148142 	0xffffffffffffffff,	/* maximum segment size */
3406349Sqs148142 	5,			/* scatter/gather list length */
3416349Sqs148142 	(unsigned int)1,	/* granularity */
3426349Sqs148142 	0			/* attribute flags */
3436349Sqs148142 };
3446349Sqs148142 
3456349Sqs148142 ddi_dma_attr_t hxge_rx_dma_attr = {
3466349Sqs148142 	DMA_ATTR_V0,		/* version number. */
3476349Sqs148142 	0,			/* low address */
3486349Sqs148142 	0xffffffffffffffff,	/* high address */
3496349Sqs148142 	0xffffffffffffffff,	/* address counter max */
3506349Sqs148142 	0x10000,		/* alignment */
3516349Sqs148142 	0xfc00fc,		/* dlim_burstsizes */
3526349Sqs148142 	0x1,			/* minimum transfer size */
3536349Sqs148142 	0xffffffffffffffff,	/* maximum transfer size */
3546349Sqs148142 	0xffffffffffffffff,	/* maximum segment size */
3556349Sqs148142 	1,			/* scatter/gather list length */
3566349Sqs148142 	(unsigned int)1,	/* granularity */
3576349Sqs148142 	DDI_DMA_RELAXED_ORDERING /* attribute flags */
3586349Sqs148142 };
3596349Sqs148142 
3606349Sqs148142 ddi_dma_lim_t hxge_dma_limits = {
3616349Sqs148142 	(uint_t)0,		/* dlim_addr_lo */
3626349Sqs148142 	(uint_t)0xffffffff,	/* dlim_addr_hi */
3636349Sqs148142 	(uint_t)0xffffffff,	/* dlim_cntr_max */
3646349Sqs148142 	(uint_t)0xfc00fc,	/* dlim_burstsizes for 32 and 64 bit xfers */
3656349Sqs148142 	0x1,			/* dlim_minxfer */
3666349Sqs148142 	1024			/* dlim_speed */
3676349Sqs148142 };
3686349Sqs148142 
3696349Sqs148142 dma_method_t hxge_force_dma = DVMA;
3706349Sqs148142 
3716349Sqs148142 /*
3726349Sqs148142  * dma chunk sizes.
3736349Sqs148142  *
3746349Sqs148142  * Try to allocate the largest possible size
3756349Sqs148142  * so that fewer number of dma chunks would be managed
3766349Sqs148142  */
3776349Sqs148142 size_t alloc_sizes[] = {
3786349Sqs148142     0x1000, 0x2000, 0x4000, 0x8000,
3796349Sqs148142     0x10000, 0x20000, 0x40000, 0x80000,
3806349Sqs148142     0x100000, 0x200000, 0x400000, 0x800000, 0x1000000
3816349Sqs148142 };
3826349Sqs148142 
3836349Sqs148142 /*
3846349Sqs148142  * Translate "dev_t" to a pointer to the associated "dev_info_t".
3856349Sqs148142  */
3866349Sqs148142 static int
hxge_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)3876349Sqs148142 hxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
3886349Sqs148142 {
3896349Sqs148142 	p_hxge_t	hxgep = NULL;
3906349Sqs148142 	int		instance;
3916349Sqs148142 	int		status = DDI_SUCCESS;
3928718SMichael.Speer@Sun.COM 	int		i;
3936349Sqs148142 
3946349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_attach"));
3956349Sqs148142 
3966349Sqs148142 	/*
3976349Sqs148142 	 * Get the device instance since we'll need to setup or retrieve a soft
3986349Sqs148142 	 * state for this instance.
3996349Sqs148142 	 */
4006349Sqs148142 	instance = ddi_get_instance(dip);
4016349Sqs148142 
4026349Sqs148142 	switch (cmd) {
4036349Sqs148142 	case DDI_ATTACH:
4046349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_ATTACH"));
4056349Sqs148142 		break;
4066349Sqs148142 
4076349Sqs148142 	case DDI_RESUME:
4086349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_RESUME"));
4096349Sqs148142 		hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance);
4106349Sqs148142 		if (hxgep == NULL) {
4116349Sqs148142 			status = DDI_FAILURE;
4126349Sqs148142 			break;
4136349Sqs148142 		}
4146349Sqs148142 		if (hxgep->dip != dip) {
4156349Sqs148142 			status = DDI_FAILURE;
4166349Sqs148142 			break;
4176349Sqs148142 		}
4186349Sqs148142 		if (hxgep->suspended == DDI_PM_SUSPEND) {
4196349Sqs148142 			status = ddi_dev_is_needed(hxgep->dip, 0, 1);
4206349Sqs148142 		} else {
4216349Sqs148142 			(void) hxge_resume(hxgep);
4226349Sqs148142 		}
4236349Sqs148142 		goto hxge_attach_exit;
4246349Sqs148142 
4256349Sqs148142 	case DDI_PM_RESUME:
4266349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_RESUME"));
4276349Sqs148142 		hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance);
4286349Sqs148142 		if (hxgep == NULL) {
4296349Sqs148142 			status = DDI_FAILURE;
4306349Sqs148142 			break;
4316349Sqs148142 		}
4326349Sqs148142 		if (hxgep->dip != dip) {
4336349Sqs148142 			status = DDI_FAILURE;
4346349Sqs148142 			break;
4356349Sqs148142 		}
4366349Sqs148142 		(void) hxge_resume(hxgep);
4376349Sqs148142 		goto hxge_attach_exit;
4386349Sqs148142 
4396349Sqs148142 	default:
4406349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing unknown"));
4416349Sqs148142 		status = DDI_FAILURE;
4426349Sqs148142 		goto hxge_attach_exit;
4436349Sqs148142 	}
4446349Sqs148142 
4456349Sqs148142 	if (ddi_soft_state_zalloc(hxge_list, instance) == DDI_FAILURE) {
4466349Sqs148142 		status = DDI_FAILURE;
4476349Sqs148142 		HXGE_ERROR_MSG((hxgep, DDI_CTL,
4486349Sqs148142 		    "ddi_soft_state_zalloc failed"));
4496349Sqs148142 		goto hxge_attach_exit;
4506349Sqs148142 	}
4516349Sqs148142 
4526349Sqs148142 	hxgep = ddi_get_soft_state(hxge_list, instance);
4536349Sqs148142 	if (hxgep == NULL) {
4546349Sqs148142 		status = HXGE_ERROR;
4556349Sqs148142 		HXGE_ERROR_MSG((hxgep, DDI_CTL,
4566349Sqs148142 		    "ddi_get_soft_state failed"));
4576349Sqs148142 		goto hxge_attach_fail2;
4586349Sqs148142 	}
4596349Sqs148142 
4606349Sqs148142 	hxgep->drv_state = 0;
4616349Sqs148142 	hxgep->dip = dip;
4626349Sqs148142 	hxgep->instance = instance;
4636349Sqs148142 	hxgep->p_dip = ddi_get_parent(dip);
4646349Sqs148142 	hxgep->hxge_debug_level = hxge_debug_level;
4656349Sqs148142 	hpi_debug_level = hxge_debug_level;
4666349Sqs148142 
4678718SMichael.Speer@Sun.COM 	/*
4688718SMichael.Speer@Sun.COM 	 * Initialize MMAC struture.
4698718SMichael.Speer@Sun.COM 	 */
4708718SMichael.Speer@Sun.COM 	(void) hxge_pfc_num_macs_get(hxgep, &hxgep->mmac.total);
4718718SMichael.Speer@Sun.COM 	hxgep->mmac.available = hxgep->mmac.total;
4728718SMichael.Speer@Sun.COM 	for (i = 0; i < hxgep->mmac.total; i++) {
4738718SMichael.Speer@Sun.COM 		hxgep->mmac.addrs[i].set = B_FALSE;
4748718SMichael.Speer@Sun.COM 		hxgep->mmac.addrs[i].primary = B_FALSE;
4758718SMichael.Speer@Sun.COM 	}
4768718SMichael.Speer@Sun.COM 
47711257SMichael.Speer@Sun.COM 	hxge_fm_init(hxgep, &hxge_dev_reg_acc_attr, &hxge_dev_desc_dma_acc_attr,
47811257SMichael.Speer@Sun.COM 	    &hxge_rx_dma_attr);
4796349Sqs148142 
4806349Sqs148142 	status = hxge_map_regs(hxgep);
4816349Sqs148142 	if (status != HXGE_OK) {
4826349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_map_regs failed"));
4836349Sqs148142 		goto hxge_attach_fail3;
4846349Sqs148142 	}
4856349Sqs148142 
4866349Sqs148142 	status = hxge_init_common_dev(hxgep);
4876349Sqs148142 	if (status != HXGE_OK) {
4886349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4896349Sqs148142 		    "hxge_init_common_dev failed"));
4906349Sqs148142 		goto hxge_attach_fail4;
4916349Sqs148142 	}
4926349Sqs148142 
4936349Sqs148142 	/*
4946349Sqs148142 	 * Setup the Ndd parameters for this instance.
4956349Sqs148142 	 */
4966349Sqs148142 	hxge_init_param(hxgep);
4976349Sqs148142 
4986349Sqs148142 	/*
4996349Sqs148142 	 * Setup Register Tracing Buffer.
5006349Sqs148142 	 */
5016349Sqs148142 	hpi_rtrace_buf_init((rtrace_t *)&hpi_rtracebuf);
5026349Sqs148142 
5036349Sqs148142 	/* init stats ptr */
5046349Sqs148142 	hxge_init_statsp(hxgep);
5056349Sqs148142 
5067584SQiyan.Sun@Sun.COM 	status = hxge_setup_mutexes(hxgep);
5077584SQiyan.Sun@Sun.COM 	if (status != HXGE_OK) {
5087584SQiyan.Sun@Sun.COM 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set mutex failed"));
5097584SQiyan.Sun@Sun.COM 		goto hxge_attach_fail;
5107584SQiyan.Sun@Sun.COM 	}
5117584SQiyan.Sun@Sun.COM 
5128791SMichael.Speer@Sun.COM 	/* Scrub the MSI-X memory */
5138791SMichael.Speer@Sun.COM 	hxge_msix_init(hxgep);
5148791SMichael.Speer@Sun.COM 
5156349Sqs148142 	status = hxge_get_config_properties(hxgep);
5166349Sqs148142 	if (status != HXGE_OK) {
5176349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "get_hw create failed"));
5186349Sqs148142 		goto hxge_attach_fail;
5196349Sqs148142 	}
5206349Sqs148142 
5216349Sqs148142 	/*
5226349Sqs148142 	 * Setup the Kstats for the driver.
5236349Sqs148142 	 */
5246349Sqs148142 	hxge_setup_kstats(hxgep);
5256349Sqs148142 	hxge_setup_param(hxgep);
5266349Sqs148142 
5276349Sqs148142 	status = hxge_setup_system_dma_pages(hxgep);
5286349Sqs148142 	if (status != HXGE_OK) {
5296349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "set dma page failed"));
5306349Sqs148142 		goto hxge_attach_fail;
5316349Sqs148142 	}
5326349Sqs148142 
5336349Sqs148142 	hxge_hw_id_init(hxgep);
5346349Sqs148142 	hxge_hw_init_niu_common(hxgep);
5356349Sqs148142 
5366349Sqs148142 	status = hxge_setup_dev(hxgep);
5376349Sqs148142 	if (status != DDI_SUCCESS) {
5386349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set dev failed"));
5396349Sqs148142 		goto hxge_attach_fail;
5406349Sqs148142 	}
5416349Sqs148142 
5426349Sqs148142 	status = hxge_add_intrs(hxgep);
5436349Sqs148142 	if (status != DDI_SUCCESS) {
5446349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "add_intr failed"));
5456349Sqs148142 		goto hxge_attach_fail;
5466349Sqs148142 	}
5476349Sqs148142 
5486349Sqs148142 	/*
5496349Sqs148142 	 * Enable interrupts.
5506349Sqs148142 	 */
5516349Sqs148142 	hxge_intrs_enable(hxgep);
5526349Sqs148142 
5536349Sqs148142 	if ((status = hxge_mac_register(hxgep)) != HXGE_OK) {
5546349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL,
5556349Sqs148142 		    "unable to register to mac layer (%d)", status));
5566349Sqs148142 		goto hxge_attach_fail;
5576349Sqs148142 	}
5587584SQiyan.Sun@Sun.COM 	mac_link_update(hxgep->mach, LINK_STATE_UNKNOWN);
5596349Sqs148142 
5606349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "registered to mac (instance %d)",
5616349Sqs148142 	    instance));
5626349Sqs148142 
5636349Sqs148142 	goto hxge_attach_exit;
5646349Sqs148142 
5656349Sqs148142 hxge_attach_fail:
5666349Sqs148142 	hxge_unattach(hxgep);
5676349Sqs148142 	goto hxge_attach_fail1;
5686349Sqs148142 
5696349Sqs148142 hxge_attach_fail5:
5706349Sqs148142 	/*
5716349Sqs148142 	 * Tear down the ndd parameters setup.
5726349Sqs148142 	 */
5736349Sqs148142 	hxge_destroy_param(hxgep);
5746349Sqs148142 
5756349Sqs148142 	/*
5766349Sqs148142 	 * Tear down the kstat setup.
5776349Sqs148142 	 */
5786349Sqs148142 	hxge_destroy_kstats(hxgep);
5796349Sqs148142 
5806349Sqs148142 hxge_attach_fail4:
5816349Sqs148142 	if (hxgep->hxge_hw_p) {
5826349Sqs148142 		hxge_uninit_common_dev(hxgep);
5836349Sqs148142 		hxgep->hxge_hw_p = NULL;
5846349Sqs148142 	}
5856349Sqs148142 hxge_attach_fail3:
5866349Sqs148142 	/*
5876349Sqs148142 	 * Unmap the register setup.
5886349Sqs148142 	 */
5896349Sqs148142 	hxge_unmap_regs(hxgep);
5906349Sqs148142 
5916349Sqs148142 	hxge_fm_fini(hxgep);
5926349Sqs148142 
5936349Sqs148142 hxge_attach_fail2:
5946349Sqs148142 	ddi_soft_state_free(hxge_list, hxgep->instance);
5956349Sqs148142 
5966349Sqs148142 hxge_attach_fail1:
5976349Sqs148142 	if (status != HXGE_OK)
5986349Sqs148142 		status = (HXGE_ERROR | HXGE_DDI_FAILED);
5996349Sqs148142 	hxgep = NULL;
6006349Sqs148142 
6016349Sqs148142 hxge_attach_exit:
6026349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_attach status = 0x%08x",
6036349Sqs148142 	    status));
6046349Sqs148142 
6056349Sqs148142 	return (status);
6066349Sqs148142 }
6076349Sqs148142 
6086349Sqs148142 static int
hxge_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)6096349Sqs148142 hxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
6106349Sqs148142 {
6116349Sqs148142 	int		status = DDI_SUCCESS;
6126349Sqs148142 	int		instance;
6136349Sqs148142 	p_hxge_t	hxgep = NULL;
6146349Sqs148142 
6156349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_detach"));
6166349Sqs148142 	instance = ddi_get_instance(dip);
6176349Sqs148142 	hxgep = ddi_get_soft_state(hxge_list, instance);
6186349Sqs148142 	if (hxgep == NULL) {
6196349Sqs148142 		status = DDI_FAILURE;
6206349Sqs148142 		goto hxge_detach_exit;
6216349Sqs148142 	}
6226349Sqs148142 
6236349Sqs148142 	switch (cmd) {
6246349Sqs148142 	case DDI_DETACH:
6256349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_DETACH"));
6266349Sqs148142 		break;
6276349Sqs148142 
6286349Sqs148142 	case DDI_PM_SUSPEND:
6296349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
6306349Sqs148142 		hxgep->suspended = DDI_PM_SUSPEND;
6316349Sqs148142 		hxge_suspend(hxgep);
6326349Sqs148142 		break;
6336349Sqs148142 
6346349Sqs148142 	case DDI_SUSPEND:
6356349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_SUSPEND"));
6366349Sqs148142 		if (hxgep->suspended != DDI_PM_SUSPEND) {
6376349Sqs148142 			hxgep->suspended = DDI_SUSPEND;
6386349Sqs148142 			hxge_suspend(hxgep);
6396349Sqs148142 		}
6406349Sqs148142 		break;
6416349Sqs148142 
6426349Sqs148142 	default:
6436349Sqs148142 		status = DDI_FAILURE;
6446349Sqs148142 		break;
6456349Sqs148142 	}
6466349Sqs148142 
6476349Sqs148142 	if (cmd != DDI_DETACH)
6486349Sqs148142 		goto hxge_detach_exit;
6496349Sqs148142 
6506349Sqs148142 	/*
6516349Sqs148142 	 * Stop the xcvr polling.
6526349Sqs148142 	 */
6536349Sqs148142 	hxgep->suspended = cmd;
6546349Sqs148142 
6556349Sqs148142 	if (hxgep->mach && (status = mac_unregister(hxgep->mach)) != 0) {
6566349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
6576349Sqs148142 		    "<== hxge_detach status = 0x%08X", status));
6586349Sqs148142 		return (DDI_FAILURE);
6596349Sqs148142 	}
6606349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
6616349Sqs148142 	    "<== hxge_detach (mac_unregister) status = 0x%08X", status));
6626349Sqs148142 
6636349Sqs148142 	hxge_unattach(hxgep);
6646349Sqs148142 	hxgep = NULL;
6656349Sqs148142 
6666349Sqs148142 hxge_detach_exit:
6676349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_detach status = 0x%08X",
6686349Sqs148142 	    status));
6696349Sqs148142 
6706349Sqs148142 	return (status);
6716349Sqs148142 }
6726349Sqs148142 
6736349Sqs148142 static void
hxge_unattach(p_hxge_t hxgep)6746349Sqs148142 hxge_unattach(p_hxge_t hxgep)
6756349Sqs148142 {
6766349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unattach"));
6776349Sqs148142 
6786349Sqs148142 	if (hxgep == NULL || hxgep->dev_regs == NULL) {
6796349Sqs148142 		return;
6806349Sqs148142 	}
6816349Sqs148142 
6826349Sqs148142 	if (hxgep->hxge_hw_p) {
6836349Sqs148142 		hxge_uninit_common_dev(hxgep);
6846349Sqs148142 		hxgep->hxge_hw_p = NULL;
6856349Sqs148142 	}
6866349Sqs148142 
6876349Sqs148142 	if (hxgep->hxge_timerid) {
6886349Sqs148142 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
6896349Sqs148142 		hxgep->hxge_timerid = 0;
6906349Sqs148142 	}
6916349Sqs148142 
69211257SMichael.Speer@Sun.COM 	/* Stop interrupts. */
69311257SMichael.Speer@Sun.COM 	hxge_intrs_disable(hxgep);
69411257SMichael.Speer@Sun.COM 
6956349Sqs148142 	/* Stop any further interrupts. */
6966349Sqs148142 	hxge_remove_intrs(hxgep);
6976349Sqs148142 
6986349Sqs148142 	/* Stop the device and free resources. */
6996349Sqs148142 	hxge_destroy_dev(hxgep);
7006349Sqs148142 
7016349Sqs148142 	/* Tear down the ndd parameters setup. */
7026349Sqs148142 	hxge_destroy_param(hxgep);
7036349Sqs148142 
7046349Sqs148142 	/* Tear down the kstat setup. */
7056349Sqs148142 	hxge_destroy_kstats(hxgep);
7066349Sqs148142 
7076349Sqs148142 	/*
7086349Sqs148142 	 * Remove the list of ndd parameters which were setup during attach.
7096349Sqs148142 	 */
7106349Sqs148142 	if (hxgep->dip) {
7116349Sqs148142 		HXGE_DEBUG_MSG((hxgep, OBP_CTL,
7126349Sqs148142 		    " hxge_unattach: remove all properties"));
7136349Sqs148142 		(void) ddi_prop_remove_all(hxgep->dip);
7146349Sqs148142 	}
7156349Sqs148142 
7166349Sqs148142 	/*
7176864Sqs148142 	 * Reset RDC, TDC, PFC, and VMAC blocks from PEU to clear any
7186864Sqs148142 	 * previous state before unmapping the registers.
7196864Sqs148142 	 */
7206864Sqs148142 	HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, 0x0000001E);
7216864Sqs148142 	HXGE_DELAY(1000);
7226864Sqs148142 
7236864Sqs148142 	/*
7246349Sqs148142 	 * Unmap the register setup.
7256349Sqs148142 	 */
7266349Sqs148142 	hxge_unmap_regs(hxgep);
7276349Sqs148142 
7286349Sqs148142 	hxge_fm_fini(hxgep);
7296349Sqs148142 
7307584SQiyan.Sun@Sun.COM 	/* Destroy all mutexes.  */
7317584SQiyan.Sun@Sun.COM 	hxge_destroy_mutexes(hxgep);
7327584SQiyan.Sun@Sun.COM 
7336349Sqs148142 	/*
7346349Sqs148142 	 * Free the soft state data structures allocated with this instance.
7356349Sqs148142 	 */
7366349Sqs148142 	ddi_soft_state_free(hxge_list, hxgep->instance);
7376349Sqs148142 
7386349Sqs148142 	HXGE_DEBUG_MSG((NULL, DDI_CTL, "<== hxge_unattach"));
7396349Sqs148142 }
7406349Sqs148142 
7416349Sqs148142 static hxge_status_t
hxge_map_regs(p_hxge_t hxgep)7426349Sqs148142 hxge_map_regs(p_hxge_t hxgep)
7436349Sqs148142 {
7446349Sqs148142 	int		ddi_status = DDI_SUCCESS;
7456349Sqs148142 	p_dev_regs_t	dev_regs;
7466349Sqs148142 
7476349Sqs148142 #ifdef	HXGE_DEBUG
7486349Sqs148142 	char		*sysname;
7496349Sqs148142 #endif
7506349Sqs148142 
7516349Sqs148142 	off_t		regsize;
7526349Sqs148142 	hxge_status_t	status = HXGE_OK;
7536349Sqs148142 	int		nregs;
7546349Sqs148142 
7556349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_map_regs"));
7566349Sqs148142 
7576349Sqs148142 	if (ddi_dev_nregs(hxgep->dip, &nregs) != DDI_SUCCESS)
7586349Sqs148142 		return (HXGE_ERROR);
7596349Sqs148142 
7606349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_regs: nregs: %d", nregs));
7616349Sqs148142 
7626349Sqs148142 	hxgep->dev_regs = NULL;
7636349Sqs148142 	dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
7646349Sqs148142 	dev_regs->hxge_regh = NULL;
7656349Sqs148142 	dev_regs->hxge_pciregh = NULL;
7666349Sqs148142 	dev_regs->hxge_msix_regh = NULL;
7676349Sqs148142 
7686349Sqs148142 	(void) ddi_dev_regsize(hxgep->dip, 0, &regsize);
7696349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
7706349Sqs148142 	    "hxge_map_regs: pci config size 0x%x", regsize));
7716349Sqs148142 
7726349Sqs148142 	ddi_status = ddi_regs_map_setup(hxgep->dip, 0,
7736349Sqs148142 	    (caddr_t *)&(dev_regs->hxge_pciregp), 0, 0,
7746349Sqs148142 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_pciregh);
7756349Sqs148142 	if (ddi_status != DDI_SUCCESS) {
7766349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7776349Sqs148142 		    "ddi_map_regs, hxge bus config regs failed"));
7786349Sqs148142 		goto hxge_map_regs_fail0;
7796349Sqs148142 	}
7806349Sqs148142 
7816349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
7826349Sqs148142 	    "hxge_map_reg: PCI config addr 0x%0llx handle 0x%0llx",
7836349Sqs148142 	    dev_regs->hxge_pciregp,
7846349Sqs148142 	    dev_regs->hxge_pciregh));
7856349Sqs148142 
7866349Sqs148142 	(void) ddi_dev_regsize(hxgep->dip, 1, &regsize);
7876349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
7886349Sqs148142 	    "hxge_map_regs: pio size 0x%x", regsize));
7896349Sqs148142 
7906349Sqs148142 	/* set up the device mapped register */
7916349Sqs148142 	ddi_status = ddi_regs_map_setup(hxgep->dip, 1,
7926349Sqs148142 	    (caddr_t *)&(dev_regs->hxge_regp), 0, 0,
7936349Sqs148142 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_regh);
7946349Sqs148142 
7956349Sqs148142 	if (ddi_status != DDI_SUCCESS) {
7966349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7976349Sqs148142 		    "ddi_map_regs for Hydra global reg failed"));
7986349Sqs148142 		goto hxge_map_regs_fail1;
7996349Sqs148142 	}
8006349Sqs148142 
8016349Sqs148142 	/* set up the msi/msi-x mapped register */
8026349Sqs148142 	(void) ddi_dev_regsize(hxgep->dip, 2, &regsize);
8036349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8046349Sqs148142 	    "hxge_map_regs: msix size 0x%x", regsize));
8056349Sqs148142 
8066349Sqs148142 	ddi_status = ddi_regs_map_setup(hxgep->dip, 2,
8076349Sqs148142 	    (caddr_t *)&(dev_regs->hxge_msix_regp), 0, 0,
8086349Sqs148142 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_msix_regh);
8096349Sqs148142 
8106349Sqs148142 	if (ddi_status != DDI_SUCCESS) {
8116349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
8126349Sqs148142 		    "ddi_map_regs for msi reg failed"));
8136349Sqs148142 		goto hxge_map_regs_fail2;
8146349Sqs148142 	}
8156349Sqs148142 
8166349Sqs148142 	hxgep->dev_regs = dev_regs;
8176349Sqs148142 
8186349Sqs148142 	HPI_PCI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_pciregh);
8196349Sqs148142 	HPI_PCI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_pciregp);
8206349Sqs148142 	HPI_MSI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_msix_regh);
8216349Sqs148142 	HPI_MSI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_msix_regp);
8226349Sqs148142 
8236349Sqs148142 	HPI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh);
8246349Sqs148142 	HPI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp);
8256349Sqs148142 
8266349Sqs148142 	HPI_REG_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh);
8276349Sqs148142 	HPI_REG_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp);
8286349Sqs148142 
8296349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_reg: hardware addr 0x%0llx "
8306349Sqs148142 	    " handle 0x%0llx", dev_regs->hxge_regp, dev_regs->hxge_regh));
8316349Sqs148142 
8326349Sqs148142 	goto hxge_map_regs_exit;
8336349Sqs148142 
8346349Sqs148142 hxge_map_regs_fail3:
8356349Sqs148142 	if (dev_regs->hxge_msix_regh) {
8366349Sqs148142 		ddi_regs_map_free(&dev_regs->hxge_msix_regh);
8376349Sqs148142 	}
8386349Sqs148142 
8396349Sqs148142 hxge_map_regs_fail2:
8406349Sqs148142 	if (dev_regs->hxge_regh) {
8416349Sqs148142 		ddi_regs_map_free(&dev_regs->hxge_regh);
8426349Sqs148142 	}
8436349Sqs148142 
8446349Sqs148142 hxge_map_regs_fail1:
8456349Sqs148142 	if (dev_regs->hxge_pciregh) {
8466349Sqs148142 		ddi_regs_map_free(&dev_regs->hxge_pciregh);
8476349Sqs148142 	}
8486349Sqs148142 
8496349Sqs148142 hxge_map_regs_fail0:
8506349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "Freeing register set memory"));
8516349Sqs148142 	kmem_free(dev_regs, sizeof (dev_regs_t));
8526349Sqs148142 
8536349Sqs148142 hxge_map_regs_exit:
8546349Sqs148142 	if (ddi_status != DDI_SUCCESS)
8556349Sqs148142 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
8566349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_map_regs"));
8576349Sqs148142 	return (status);
8586349Sqs148142 }
8596349Sqs148142 
8606349Sqs148142 static void
hxge_unmap_regs(p_hxge_t hxgep)8616349Sqs148142 hxge_unmap_regs(p_hxge_t hxgep)
8626349Sqs148142 {
8636349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unmap_regs"));
8646349Sqs148142 	if (hxgep->dev_regs) {
8656349Sqs148142 		if (hxgep->dev_regs->hxge_pciregh) {
8666349Sqs148142 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8676349Sqs148142 			    "==> hxge_unmap_regs: bus"));
8686349Sqs148142 			ddi_regs_map_free(&hxgep->dev_regs->hxge_pciregh);
8696349Sqs148142 			hxgep->dev_regs->hxge_pciregh = NULL;
8706349Sqs148142 		}
8716349Sqs148142 
8726349Sqs148142 		if (hxgep->dev_regs->hxge_regh) {
8736349Sqs148142 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8746349Sqs148142 			    "==> hxge_unmap_regs: device registers"));
8756349Sqs148142 			ddi_regs_map_free(&hxgep->dev_regs->hxge_regh);
8766349Sqs148142 			hxgep->dev_regs->hxge_regh = NULL;
8776349Sqs148142 		}
8786349Sqs148142 
8796349Sqs148142 		if (hxgep->dev_regs->hxge_msix_regh) {
8806349Sqs148142 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8816349Sqs148142 			    "==> hxge_unmap_regs: device interrupts"));
8826349Sqs148142 			ddi_regs_map_free(&hxgep->dev_regs->hxge_msix_regh);
8836349Sqs148142 			hxgep->dev_regs->hxge_msix_regh = NULL;
8846349Sqs148142 		}
8856349Sqs148142 		kmem_free(hxgep->dev_regs, sizeof (dev_regs_t));
8866349Sqs148142 		hxgep->dev_regs = NULL;
8876349Sqs148142 	}
8886349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_unmap_regs"));
8896349Sqs148142 }
8906349Sqs148142 
8916349Sqs148142 static hxge_status_t
hxge_setup_mutexes(p_hxge_t hxgep)8926349Sqs148142 hxge_setup_mutexes(p_hxge_t hxgep)
8936349Sqs148142 {
8946349Sqs148142 	int		ddi_status = DDI_SUCCESS;
8956349Sqs148142 	hxge_status_t	status = HXGE_OK;
8966349Sqs148142 
8976349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_mutexes"));
8986349Sqs148142 
8996349Sqs148142 	/*
9006349Sqs148142 	 * Get the interrupt cookie so the mutexes can be Initialised.
9016349Sqs148142 	 */
9026349Sqs148142 	ddi_status = ddi_get_iblock_cookie(hxgep->dip, 0,
9036349Sqs148142 	    &hxgep->interrupt_cookie);
9046349Sqs148142 
9056349Sqs148142 	if (ddi_status != DDI_SUCCESS) {
9066349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9076349Sqs148142 		    "<== hxge_setup_mutexes: failed 0x%x", ddi_status));
9086349Sqs148142 		goto hxge_setup_mutexes_exit;
9096349Sqs148142 	}
9106349Sqs148142 
9116349Sqs148142 	/*
9126349Sqs148142 	 * Initialize mutex's for this device.
9136349Sqs148142 	 */
9146349Sqs148142 	MUTEX_INIT(hxgep->genlock, NULL,
9156349Sqs148142 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
91610091SMichael.Speer@Sun.COM 	MUTEX_INIT(&hxgep->vmac_lock, NULL,
91710091SMichael.Speer@Sun.COM 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
9186349Sqs148142 	MUTEX_INIT(&hxgep->ouraddr_lock, NULL,
9196349Sqs148142 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
9206349Sqs148142 	RW_INIT(&hxgep->filter_lock, NULL,
9216349Sqs148142 	    RW_DRIVER, (void *) hxgep->interrupt_cookie);
9226864Sqs148142 	MUTEX_INIT(&hxgep->pio_lock, NULL,
9236864Sqs148142 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
9247584SQiyan.Sun@Sun.COM 	MUTEX_INIT(&hxgep->timeout.lock, NULL,
9257584SQiyan.Sun@Sun.COM 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
9266349Sqs148142 
9276349Sqs148142 hxge_setup_mutexes_exit:
9286349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
9296349Sqs148142 	    "<== hxge_setup_mutexes status = %x", status));
9306349Sqs148142 
9316349Sqs148142 	if (ddi_status != DDI_SUCCESS)
9326349Sqs148142 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
9336349Sqs148142 
9346349Sqs148142 	return (status);
9356349Sqs148142 }
9366349Sqs148142 
9376349Sqs148142 static void
hxge_destroy_mutexes(p_hxge_t hxgep)9386349Sqs148142 hxge_destroy_mutexes(p_hxge_t hxgep)
9396349Sqs148142 {
9406349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_mutexes"));
9416349Sqs148142 	RW_DESTROY(&hxgep->filter_lock);
94210091SMichael.Speer@Sun.COM 	MUTEX_DESTROY(&hxgep->vmac_lock);
9436349Sqs148142 	MUTEX_DESTROY(&hxgep->ouraddr_lock);
9446349Sqs148142 	MUTEX_DESTROY(hxgep->genlock);
9456864Sqs148142 	MUTEX_DESTROY(&hxgep->pio_lock);
9467584SQiyan.Sun@Sun.COM 	MUTEX_DESTROY(&hxgep->timeout.lock);
9476349Sqs148142 
9486349Sqs148142 	if (hxge_debug_init == 1) {
9496349Sqs148142 		MUTEX_DESTROY(&hxgedebuglock);
9506349Sqs148142 		hxge_debug_init = 0;
9516349Sqs148142 	}
9526349Sqs148142 
9536349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_mutexes"));
9546349Sqs148142 }
9556349Sqs148142 
9566349Sqs148142 hxge_status_t
hxge_init(p_hxge_t hxgep)9576349Sqs148142 hxge_init(p_hxge_t hxgep)
9586349Sqs148142 {
9596349Sqs148142 	hxge_status_t status = HXGE_OK;
9606349Sqs148142 
9616349Sqs148142 	HXGE_DEBUG_MSG((hxgep, STR_CTL, "==> hxge_init"));
9626349Sqs148142 
9636349Sqs148142 	if (hxgep->drv_state & STATE_HW_INITIALIZED) {
9646349Sqs148142 		return (status);
9656349Sqs148142 	}
9666349Sqs148142 
9676349Sqs148142 	/*
9686349Sqs148142 	 * Allocate system memory for the receive/transmit buffer blocks and
9696349Sqs148142 	 * receive/transmit descriptor rings.
9706349Sqs148142 	 */
9716349Sqs148142 	status = hxge_alloc_mem_pool(hxgep);
9726349Sqs148142 	if (status != HXGE_OK) {
9736349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "alloc mem failed\n"));
9746349Sqs148142 		goto hxge_init_fail1;
9756349Sqs148142 	}
9766349Sqs148142 
9776349Sqs148142 	/*
9786349Sqs148142 	 * Initialize and enable TXDMA channels.
9796349Sqs148142 	 */
9806349Sqs148142 	status = hxge_init_txdma_channels(hxgep);
9816349Sqs148142 	if (status != HXGE_OK) {
9826349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init txdma failed\n"));
9836349Sqs148142 		goto hxge_init_fail3;
9846349Sqs148142 	}
9856349Sqs148142 
9866349Sqs148142 	/*
9876349Sqs148142 	 * Initialize and enable RXDMA channels.
9886349Sqs148142 	 */
9896349Sqs148142 	status = hxge_init_rxdma_channels(hxgep);
9906349Sqs148142 	if (status != HXGE_OK) {
9916349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init rxdma failed\n"));
9926349Sqs148142 		goto hxge_init_fail4;
9936349Sqs148142 	}
9946349Sqs148142 
9956349Sqs148142 	/*
9966349Sqs148142 	 * Initialize TCAM
9976349Sqs148142 	 */
9986349Sqs148142 	status = hxge_classify_init(hxgep);
9996349Sqs148142 	if (status != HXGE_OK) {
10006349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init classify failed\n"));
10016349Sqs148142 		goto hxge_init_fail5;
10026349Sqs148142 	}
10036349Sqs148142 
10046349Sqs148142 	/*
10056349Sqs148142 	 * Initialize the VMAC block.
10066349Sqs148142 	 */
10076349Sqs148142 	status = hxge_vmac_init(hxgep);
10086349Sqs148142 	if (status != HXGE_OK) {
10096349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init MAC failed\n"));
10106349Sqs148142 		goto hxge_init_fail5;
10116349Sqs148142 	}
10126349Sqs148142 
10136349Sqs148142 	/* Bringup - this may be unnecessary when PXE and FCODE available */
10146349Sqs148142 	status = hxge_pfc_set_default_mac_addr(hxgep);
10156349Sqs148142 	if (status != HXGE_OK) {
10166349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
10176349Sqs148142 		    "Default Address Failure\n"));
10186349Sqs148142 		goto hxge_init_fail5;
10196349Sqs148142 	}
10206349Sqs148142 
10216349Sqs148142 	/*
10226349Sqs148142 	 * Enable hardware interrupts.
10236349Sqs148142 	 */
10246349Sqs148142 	hxge_intr_hw_enable(hxgep);
10256349Sqs148142 	hxgep->drv_state |= STATE_HW_INITIALIZED;
10266349Sqs148142 
10276349Sqs148142 	goto hxge_init_exit;
10286349Sqs148142 
10296349Sqs148142 hxge_init_fail5:
10306349Sqs148142 	hxge_uninit_rxdma_channels(hxgep);
10316349Sqs148142 hxge_init_fail4:
10326349Sqs148142 	hxge_uninit_txdma_channels(hxgep);
10336349Sqs148142 hxge_init_fail3:
10346349Sqs148142 	hxge_free_mem_pool(hxgep);
10356349Sqs148142 hxge_init_fail1:
10366349Sqs148142 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
10376349Sqs148142 	    "<== hxge_init status (failed) = 0x%08x", status));
10386349Sqs148142 	return (status);
10396349Sqs148142 
10406349Sqs148142 hxge_init_exit:
10416349Sqs148142 
10426349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_init status = 0x%08x",
10436349Sqs148142 	    status));
10446349Sqs148142 
10456349Sqs148142 	return (status);
10466349Sqs148142 }
10476349Sqs148142 
10486349Sqs148142 timeout_id_t
hxge_start_timer(p_hxge_t hxgep,fptrv_t func,int msec)10496349Sqs148142 hxge_start_timer(p_hxge_t hxgep, fptrv_t func, int msec)
10506349Sqs148142 {
10516349Sqs148142 	if ((hxgep->suspended == 0) || (hxgep->suspended == DDI_RESUME)) {
10526349Sqs148142 		return (timeout(func, (caddr_t)hxgep,
10536349Sqs148142 		    drv_usectohz(1000 * msec)));
10546349Sqs148142 	}
10556349Sqs148142 	return (NULL);
10566349Sqs148142 }
10576349Sqs148142 
10586349Sqs148142 /*ARGSUSED*/
10596349Sqs148142 void
hxge_stop_timer(p_hxge_t hxgep,timeout_id_t timerid)10606349Sqs148142 hxge_stop_timer(p_hxge_t hxgep, timeout_id_t timerid)
10616349Sqs148142 {
10626349Sqs148142 	if (timerid) {
10636349Sqs148142 		(void) untimeout(timerid);
10646349Sqs148142 	}
10656349Sqs148142 }
10666349Sqs148142 
10676349Sqs148142 void
hxge_uninit(p_hxge_t hxgep)10686349Sqs148142 hxge_uninit(p_hxge_t hxgep)
10696349Sqs148142 {
10706349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_uninit"));
10716349Sqs148142 
10726349Sqs148142 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
10736349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL,
10746349Sqs148142 		    "==> hxge_uninit: not initialized"));
10756349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit"));
10766349Sqs148142 		return;
10776349Sqs148142 	}
10786349Sqs148142 
10796349Sqs148142 	/* Stop timer */
10806349Sqs148142 	if (hxgep->hxge_timerid) {
10816349Sqs148142 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
10826349Sqs148142 		hxgep->hxge_timerid = 0;
10836349Sqs148142 	}
10846349Sqs148142 
10856349Sqs148142 	(void) hxge_intr_hw_disable(hxgep);
10866349Sqs148142 
10876349Sqs148142 	/* Reset the receive VMAC side.  */
10886349Sqs148142 	(void) hxge_rx_vmac_disable(hxgep);
10896349Sqs148142 
10906349Sqs148142 	/* Free classification resources */
10916349Sqs148142 	(void) hxge_classify_uninit(hxgep);
10926349Sqs148142 
10936349Sqs148142 	/* Reset the transmit/receive DMA side.  */
10946349Sqs148142 	(void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_STOP);
10956349Sqs148142 	(void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_STOP);
10966349Sqs148142 
10976349Sqs148142 	hxge_uninit_txdma_channels(hxgep);
10986349Sqs148142 	hxge_uninit_rxdma_channels(hxgep);
10996349Sqs148142 
11006349Sqs148142 	/* Reset the transmit VMAC side.  */
11016349Sqs148142 	(void) hxge_tx_vmac_disable(hxgep);
11026349Sqs148142 
11036349Sqs148142 	hxge_free_mem_pool(hxgep);
11046349Sqs148142 
11056349Sqs148142 	hxgep->drv_state &= ~STATE_HW_INITIALIZED;
11066349Sqs148142 
11076349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit"));
11086349Sqs148142 }
11096349Sqs148142 
11106349Sqs148142 /*ARGSUSED*/
11116349Sqs148142 /*VARARGS*/
11126349Sqs148142 void
hxge_debug_msg(p_hxge_t hxgep,uint64_t level,char * fmt,...)11136349Sqs148142 hxge_debug_msg(p_hxge_t hxgep, uint64_t level, char *fmt, ...)
11146349Sqs148142 {
11156349Sqs148142 	char		msg_buffer[1048];
11166349Sqs148142 	char		prefix_buffer[32];
11176349Sqs148142 	int		instance;
11186349Sqs148142 	uint64_t	debug_level;
11196349Sqs148142 	int		cmn_level = CE_CONT;
11206349Sqs148142 	va_list		ap;
11216349Sqs148142 
11226349Sqs148142 	debug_level = (hxgep == NULL) ? hxge_debug_level :
11236349Sqs148142 	    hxgep->hxge_debug_level;
11246349Sqs148142 
11256349Sqs148142 	if ((level & debug_level) || (level == HXGE_NOTE) ||
11266349Sqs148142 	    (level == HXGE_ERR_CTL)) {
11276349Sqs148142 		/* do the msg processing */
11286349Sqs148142 		if (hxge_debug_init == 0) {
11296349Sqs148142 			MUTEX_INIT(&hxgedebuglock, NULL, MUTEX_DRIVER, NULL);
11306349Sqs148142 			hxge_debug_init = 1;
11316349Sqs148142 		}
11326349Sqs148142 
11336349Sqs148142 		MUTEX_ENTER(&hxgedebuglock);
11346349Sqs148142 
11356349Sqs148142 		if ((level & HXGE_NOTE)) {
11366349Sqs148142 			cmn_level = CE_NOTE;
11376349Sqs148142 		}
11386349Sqs148142 
11396349Sqs148142 		if (level & HXGE_ERR_CTL) {
11406349Sqs148142 			cmn_level = CE_WARN;
11416349Sqs148142 		}
11426349Sqs148142 
11436349Sqs148142 		va_start(ap, fmt);
11446349Sqs148142 		(void) vsprintf(msg_buffer, fmt, ap);
11456349Sqs148142 		va_end(ap);
11466349Sqs148142 
11476349Sqs148142 		if (hxgep == NULL) {
11486349Sqs148142 			instance = -1;
11496349Sqs148142 			(void) sprintf(prefix_buffer, "%s :", "hxge");
11506349Sqs148142 		} else {
11516349Sqs148142 			instance = hxgep->instance;
11526349Sqs148142 			(void) sprintf(prefix_buffer,
11536349Sqs148142 			    "%s%d :", "hxge", instance);
11546349Sqs148142 		}
11556349Sqs148142 
11566349Sqs148142 		MUTEX_EXIT(&hxgedebuglock);
11576349Sqs148142 		cmn_err(cmn_level, "%s %s\n", prefix_buffer, msg_buffer);
11586349Sqs148142 	}
11596349Sqs148142 }
11606349Sqs148142 
11616349Sqs148142 char *
hxge_dump_packet(char * addr,int size)11626349Sqs148142 hxge_dump_packet(char *addr, int size)
11636349Sqs148142 {
11646349Sqs148142 	uchar_t		*ap = (uchar_t *)addr;
11656349Sqs148142 	int		i;
11666349Sqs148142 	static char	etherbuf[1024];
11676349Sqs148142 	char		*cp = etherbuf;
11686349Sqs148142 	char		digits[] = "0123456789abcdef";
11696349Sqs148142 
11706349Sqs148142 	if (!size)
11716349Sqs148142 		size = 60;
11726349Sqs148142 
11736349Sqs148142 	if (size > MAX_DUMP_SZ) {
11746349Sqs148142 		/* Dump the leading bytes */
11756349Sqs148142 		for (i = 0; i < MAX_DUMP_SZ / 2; i++) {
11766349Sqs148142 			if (*ap > 0x0f)
11776349Sqs148142 				*cp++ = digits[*ap >> 4];
11786349Sqs148142 			*cp++ = digits[*ap++ & 0xf];
11796349Sqs148142 			*cp++ = ':';
11806349Sqs148142 		}
11816349Sqs148142 		for (i = 0; i < 20; i++)
11826349Sqs148142 			*cp++ = '.';
11836349Sqs148142 		/* Dump the last MAX_DUMP_SZ/2 bytes */
11846349Sqs148142 		ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ / 2));
11856349Sqs148142 		for (i = 0; i < MAX_DUMP_SZ / 2; i++) {
11866349Sqs148142 			if (*ap > 0x0f)
11876349Sqs148142 				*cp++ = digits[*ap >> 4];
11886349Sqs148142 			*cp++ = digits[*ap++ & 0xf];
11896349Sqs148142 			*cp++ = ':';
11906349Sqs148142 		}
11916349Sqs148142 	} else {
11926349Sqs148142 		for (i = 0; i < size; i++) {
11936349Sqs148142 			if (*ap > 0x0f)
11946349Sqs148142 				*cp++ = digits[*ap >> 4];
11956349Sqs148142 			*cp++ = digits[*ap++ & 0xf];
11966349Sqs148142 			*cp++ = ':';
11976349Sqs148142 		}
11986349Sqs148142 	}
11996349Sqs148142 	*--cp = 0;
12006349Sqs148142 	return (etherbuf);
12016349Sqs148142 }
12026349Sqs148142 
12036349Sqs148142 static void
hxge_suspend(p_hxge_t hxgep)12046349Sqs148142 hxge_suspend(p_hxge_t hxgep)
12056349Sqs148142 {
12066349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_suspend"));
12076349Sqs148142 
12088236SQiyan.Sun@Sun.COM 	/*
12098236SQiyan.Sun@Sun.COM 	 * Stop the link status timer before hxge_intrs_disable() to avoid
12108236SQiyan.Sun@Sun.COM 	 * accessing the the MSIX table simultaneously. Note that the timer
12118236SQiyan.Sun@Sun.COM 	 * routine polls for MSIX parity errors.
12128236SQiyan.Sun@Sun.COM 	 */
12137584SQiyan.Sun@Sun.COM 	MUTEX_ENTER(&hxgep->timeout.lock);
12147584SQiyan.Sun@Sun.COM 	if (hxgep->timeout.id)
12157584SQiyan.Sun@Sun.COM 		(void) untimeout(hxgep->timeout.id);
12167584SQiyan.Sun@Sun.COM 	MUTEX_EXIT(&hxgep->timeout.lock);
12177584SQiyan.Sun@Sun.COM 
12188236SQiyan.Sun@Sun.COM 	hxge_intrs_disable(hxgep);
12198236SQiyan.Sun@Sun.COM 	hxge_destroy_dev(hxgep);
12208236SQiyan.Sun@Sun.COM 
12216349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_suspend"));
12226349Sqs148142 }
12236349Sqs148142 
12246349Sqs148142 static hxge_status_t
hxge_resume(p_hxge_t hxgep)12256349Sqs148142 hxge_resume(p_hxge_t hxgep)
12266349Sqs148142 {
12276349Sqs148142 	hxge_status_t status = HXGE_OK;
12286349Sqs148142 
12296349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_resume"));
12306349Sqs148142 	hxgep->suspended = DDI_RESUME;
12316349Sqs148142 
12326349Sqs148142 	(void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_START);
12336349Sqs148142 	(void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_START);
12346349Sqs148142 
12356349Sqs148142 	(void) hxge_rx_vmac_enable(hxgep);
12366349Sqs148142 	(void) hxge_tx_vmac_enable(hxgep);
12376349Sqs148142 
12386349Sqs148142 	hxge_intrs_enable(hxgep);
12396349Sqs148142 
12406349Sqs148142 	hxgep->suspended = 0;
12416349Sqs148142 
12428236SQiyan.Sun@Sun.COM 	/*
12438236SQiyan.Sun@Sun.COM 	 * Resume the link status timer after hxge_intrs_enable to avoid
12448236SQiyan.Sun@Sun.COM 	 * accessing MSIX table simultaneously.
12458236SQiyan.Sun@Sun.COM 	 */
12467584SQiyan.Sun@Sun.COM 	MUTEX_ENTER(&hxgep->timeout.lock);
12477584SQiyan.Sun@Sun.COM 	hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep,
12487584SQiyan.Sun@Sun.COM 	    hxgep->timeout.ticks);
12497584SQiyan.Sun@Sun.COM 	MUTEX_EXIT(&hxgep->timeout.lock);
12507584SQiyan.Sun@Sun.COM 
12516349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
12526349Sqs148142 	    "<== hxge_resume status = 0x%x", status));
12536349Sqs148142 
12546349Sqs148142 	return (status);
12556349Sqs148142 }
12566349Sqs148142 
125711257SMichael.Speer@Sun.COM static hxge_status_t
hxge_setup_dev(p_hxge_t hxgep)12586349Sqs148142 hxge_setup_dev(p_hxge_t hxgep)
12596349Sqs148142 {
12606349Sqs148142 	hxge_status_t status = HXGE_OK;
12616349Sqs148142 
12626349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_dev"));
12636349Sqs148142 
12646349Sqs148142 	status = hxge_link_init(hxgep);
12656349Sqs148142 	if (fm_check_acc_handle(hxgep->dev_regs->hxge_regh) != DDI_FM_OK) {
12666349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
12676349Sqs148142 		    "Bad register acc handle"));
12686349Sqs148142 		status = HXGE_ERROR;
12696349Sqs148142 	}
12706349Sqs148142 
12716349Sqs148142 	if (status != HXGE_OK) {
12726349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MAC_CTL,
12736349Sqs148142 		    " hxge_setup_dev status (link init 0x%08x)", status));
12746349Sqs148142 		goto hxge_setup_dev_exit;
12756349Sqs148142 	}
12766349Sqs148142 
12776349Sqs148142 hxge_setup_dev_exit:
12786349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
12796349Sqs148142 	    "<== hxge_setup_dev status = 0x%08x", status));
12806349Sqs148142 
12816349Sqs148142 	return (status);
12826349Sqs148142 }
12836349Sqs148142 
12846349Sqs148142 static void
hxge_destroy_dev(p_hxge_t hxgep)12856349Sqs148142 hxge_destroy_dev(p_hxge_t hxgep)
12866349Sqs148142 {
12876349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_dev"));
12886349Sqs148142 
12896349Sqs148142 	(void) hxge_hw_stop(hxgep);
12906349Sqs148142 
12916349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_dev"));
12926349Sqs148142 }
12936349Sqs148142 
12946349Sqs148142 static hxge_status_t
hxge_setup_system_dma_pages(p_hxge_t hxgep)12956349Sqs148142 hxge_setup_system_dma_pages(p_hxge_t hxgep)
12966349Sqs148142 {
12976349Sqs148142 	int			ddi_status = DDI_SUCCESS;
12986349Sqs148142 	uint_t			count;
12996349Sqs148142 	ddi_dma_cookie_t	cookie;
13006349Sqs148142 	uint_t			iommu_pagesize;
13016349Sqs148142 	hxge_status_t		status = HXGE_OK;
13026349Sqs148142 
13036349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_system_dma_pages"));
13046349Sqs148142 
13056349Sqs148142 	hxgep->sys_page_sz = ddi_ptob(hxgep->dip, (ulong_t)1);
13066349Sqs148142 	iommu_pagesize = dvma_pagesize(hxgep->dip);
13076349Sqs148142 
13086349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
13096349Sqs148142 	    " hxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
13106349Sqs148142 	    " default_block_size %d iommu_pagesize %d",
13116349Sqs148142 	    hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1),
13126349Sqs148142 	    hxgep->rx_default_block_size, iommu_pagesize));
13136349Sqs148142 
13146349Sqs148142 	if (iommu_pagesize != 0) {
13156349Sqs148142 		if (hxgep->sys_page_sz == iommu_pagesize) {
13166349Sqs148142 			/* Hydra support up to 8K pages */
13176349Sqs148142 			if (iommu_pagesize > 0x2000)
13186349Sqs148142 				hxgep->sys_page_sz = 0x2000;
13196349Sqs148142 		} else {
13206349Sqs148142 			if (hxgep->sys_page_sz > iommu_pagesize)
13216349Sqs148142 				hxgep->sys_page_sz = iommu_pagesize;
13226349Sqs148142 		}
13236349Sqs148142 	}
13246349Sqs148142 
13256349Sqs148142 	hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1);
13266349Sqs148142 
13276349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
13286349Sqs148142 	    "==> hxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
13296349Sqs148142 	    "default_block_size %d page mask %d",
13306349Sqs148142 	    hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1),
13316349Sqs148142 	    hxgep->rx_default_block_size, hxgep->sys_page_mask));
13326349Sqs148142 
13336349Sqs148142 	switch (hxgep->sys_page_sz) {
13346349Sqs148142 	default:
13356349Sqs148142 		hxgep->sys_page_sz = 0x1000;
13366349Sqs148142 		hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1);
13376349Sqs148142 		hxgep->rx_default_block_size = 0x1000;
13386349Sqs148142 		hxgep->rx_bksize_code = RBR_BKSIZE_4K;
13396349Sqs148142 		break;
13406349Sqs148142 	case 0x1000:
13416349Sqs148142 		hxgep->rx_default_block_size = 0x1000;
13426349Sqs148142 		hxgep->rx_bksize_code = RBR_BKSIZE_4K;
13436349Sqs148142 		break;
13446349Sqs148142 	case 0x2000:
13456349Sqs148142 		hxgep->rx_default_block_size = 0x2000;
13466349Sqs148142 		hxgep->rx_bksize_code = RBR_BKSIZE_8K;
13476349Sqs148142 		break;
13486349Sqs148142 	}
13496349Sqs148142 
13506349Sqs148142 	hxge_rx_dma_attr.dma_attr_align = hxgep->sys_page_sz;
13516349Sqs148142 	hxge_tx_dma_attr.dma_attr_align = hxgep->sys_page_sz;
13526349Sqs148142 
13536349Sqs148142 	/*
13546349Sqs148142 	 * Get the system DMA burst size.
13556349Sqs148142 	 */
13566349Sqs148142 	ddi_status = ddi_dma_alloc_handle(hxgep->dip, &hxge_tx_dma_attr,
13576349Sqs148142 	    DDI_DMA_DONTWAIT, 0, &hxgep->dmasparehandle);
13586349Sqs148142 	if (ddi_status != DDI_SUCCESS) {
13596349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
13606349Sqs148142 		    "ddi_dma_alloc_handle: failed status 0x%x", ddi_status));
13616349Sqs148142 		goto hxge_get_soft_properties_exit;
13626349Sqs148142 	}
13636349Sqs148142 
13646349Sqs148142 	ddi_status = ddi_dma_addr_bind_handle(hxgep->dmasparehandle, NULL,
13656349Sqs148142 	    (caddr_t)hxgep->dmasparehandle, sizeof (hxgep->dmasparehandle),
13666349Sqs148142 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0,
13676349Sqs148142 	    &cookie, &count);
13686349Sqs148142 	if (ddi_status != DDI_DMA_MAPPED) {
13696349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
13706349Sqs148142 		    "Binding spare handle to find system burstsize failed."));
13716349Sqs148142 		ddi_status = DDI_FAILURE;
13726349Sqs148142 		goto hxge_get_soft_properties_fail1;
13736349Sqs148142 	}
13746349Sqs148142 
13756349Sqs148142 	hxgep->sys_burst_sz = ddi_dma_burstsizes(hxgep->dmasparehandle);
13766349Sqs148142 	(void) ddi_dma_unbind_handle(hxgep->dmasparehandle);
13776349Sqs148142 
13786349Sqs148142 hxge_get_soft_properties_fail1:
13796349Sqs148142 	ddi_dma_free_handle(&hxgep->dmasparehandle);
13806349Sqs148142 
13816349Sqs148142 hxge_get_soft_properties_exit:
13826349Sqs148142 
13836349Sqs148142 	if (ddi_status != DDI_SUCCESS)
13846349Sqs148142 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
13856349Sqs148142 
13866349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
13876349Sqs148142 	    "<== hxge_setup_system_dma_pages status = 0x%08x", status));
13886349Sqs148142 
13896349Sqs148142 	return (status);
13906349Sqs148142 }
13916349Sqs148142 
139211257SMichael.Speer@Sun.COM static hxge_status_t
hxge_alloc_mem_pool(p_hxge_t hxgep)13936349Sqs148142 hxge_alloc_mem_pool(p_hxge_t hxgep)
13946349Sqs148142 {
13956349Sqs148142 	hxge_status_t status = HXGE_OK;
13966349Sqs148142 
13976349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_alloc_mem_pool"));
13986349Sqs148142 
13996349Sqs148142 	status = hxge_alloc_rx_mem_pool(hxgep);
14006349Sqs148142 	if (status != HXGE_OK) {
14016349Sqs148142 		return (HXGE_ERROR);
14026349Sqs148142 	}
14036349Sqs148142 
14046349Sqs148142 	status = hxge_alloc_tx_mem_pool(hxgep);
14056349Sqs148142 	if (status != HXGE_OK) {
14066349Sqs148142 		hxge_free_rx_mem_pool(hxgep);
14076349Sqs148142 		return (HXGE_ERROR);
14086349Sqs148142 	}
14096349Sqs148142 
14106349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_alloc_mem_pool"));
14116349Sqs148142 	return (HXGE_OK);
14126349Sqs148142 }
14136349Sqs148142 
14146349Sqs148142 static void
hxge_free_mem_pool(p_hxge_t hxgep)14156349Sqs148142 hxge_free_mem_pool(p_hxge_t hxgep)
14166349Sqs148142 {
14176349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_mem_pool"));
14186349Sqs148142 
14196349Sqs148142 	hxge_free_rx_mem_pool(hxgep);
14206349Sqs148142 	hxge_free_tx_mem_pool(hxgep);
14216349Sqs148142 
14226349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_mem_pool"));
14236349Sqs148142 }
14246349Sqs148142 
14256349Sqs148142 static hxge_status_t
hxge_alloc_rx_mem_pool(p_hxge_t hxgep)14266349Sqs148142 hxge_alloc_rx_mem_pool(p_hxge_t hxgep)
14276349Sqs148142 {
14286349Sqs148142 	int			i, j;
14296349Sqs148142 	uint32_t		ndmas, st_rdc;
14306349Sqs148142 	p_hxge_dma_pt_cfg_t	p_all_cfgp;
14316349Sqs148142 	p_hxge_hw_pt_cfg_t	p_cfgp;
14326349Sqs148142 	p_hxge_dma_pool_t	dma_poolp;
14336349Sqs148142 	p_hxge_dma_common_t	*dma_buf_p;
14347618SMichael.Speer@Sun.COM 	p_hxge_dma_pool_t	dma_rbr_cntl_poolp;
14357618SMichael.Speer@Sun.COM 	p_hxge_dma_common_t	*dma_rbr_cntl_p;
14367618SMichael.Speer@Sun.COM 	p_hxge_dma_pool_t	dma_rcr_cntl_poolp;
14377618SMichael.Speer@Sun.COM 	p_hxge_dma_common_t	*dma_rcr_cntl_p;
14387618SMichael.Speer@Sun.COM 	p_hxge_dma_pool_t	dma_mbox_cntl_poolp;
14397618SMichael.Speer@Sun.COM 	p_hxge_dma_common_t	*dma_mbox_cntl_p;
14406349Sqs148142 	size_t			rx_buf_alloc_size;
14417618SMichael.Speer@Sun.COM 	size_t			rx_rbr_cntl_alloc_size;
14427618SMichael.Speer@Sun.COM 	size_t			rx_rcr_cntl_alloc_size;
14437618SMichael.Speer@Sun.COM 	size_t			rx_mbox_cntl_alloc_size;
14446349Sqs148142 	uint32_t		*num_chunks;	/* per dma */
14456349Sqs148142 	hxge_status_t		status = HXGE_OK;
14466349Sqs148142 
14476349Sqs148142 	uint32_t		hxge_port_rbr_size;
14486349Sqs148142 	uint32_t		hxge_port_rbr_spare_size;
14496349Sqs148142 	uint32_t		hxge_port_rcr_size;
14506349Sqs148142 
14516349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_mem_pool"));
14526349Sqs148142 
14536349Sqs148142 	p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
14546349Sqs148142 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
14556349Sqs148142 	st_rdc = p_cfgp->start_rdc;
14566349Sqs148142 	ndmas = p_cfgp->max_rdcs;
14576349Sqs148142 
14586349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
14596349Sqs148142 	    " hxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas));
14606349Sqs148142 
14616349Sqs148142 	/*
14626349Sqs148142 	 * Allocate memory for each receive DMA channel.
14636349Sqs148142 	 */
14646349Sqs148142 	dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t),
14656349Sqs148142 	    KM_SLEEP);
14666349Sqs148142 	dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
14676349Sqs148142 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
14686349Sqs148142 
14697618SMichael.Speer@Sun.COM 	dma_rbr_cntl_poolp = (p_hxge_dma_pool_t)
14707618SMichael.Speer@Sun.COM 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
14717618SMichael.Speer@Sun.COM 	dma_rbr_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
14727618SMichael.Speer@Sun.COM 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
14737618SMichael.Speer@Sun.COM 	dma_rcr_cntl_poolp = (p_hxge_dma_pool_t)
14746349Sqs148142 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
14757618SMichael.Speer@Sun.COM 	dma_rcr_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
14767618SMichael.Speer@Sun.COM 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
14777618SMichael.Speer@Sun.COM 	dma_mbox_cntl_poolp = (p_hxge_dma_pool_t)
14787618SMichael.Speer@Sun.COM 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
14797618SMichael.Speer@Sun.COM 	dma_mbox_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
14806349Sqs148142 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
14816349Sqs148142 
14826349Sqs148142 	num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas,
14836349Sqs148142 	    KM_SLEEP);
14846349Sqs148142 
14856349Sqs148142 	/*
14866349Sqs148142 	 * Assume that each DMA channel will be configured with default block
14876349Sqs148142 	 * size. rbr block counts are mod of batch count (16).
14886349Sqs148142 	 */
14896349Sqs148142 	hxge_port_rbr_size = p_all_cfgp->rbr_size;
14906349Sqs148142 	hxge_port_rcr_size = p_all_cfgp->rcr_size;
14916349Sqs148142 
14926349Sqs148142 	if (!hxge_port_rbr_size) {
14936349Sqs148142 		hxge_port_rbr_size = HXGE_RBR_RBB_DEFAULT;
14946349Sqs148142 	}
14956349Sqs148142 
14966349Sqs148142 	if (hxge_port_rbr_size % HXGE_RXDMA_POST_BATCH) {
14976349Sqs148142 		hxge_port_rbr_size = (HXGE_RXDMA_POST_BATCH *
14986349Sqs148142 		    (hxge_port_rbr_size / HXGE_RXDMA_POST_BATCH + 1));
14996349Sqs148142 	}
15006349Sqs148142 
15016349Sqs148142 	p_all_cfgp->rbr_size = hxge_port_rbr_size;
15026349Sqs148142 	hxge_port_rbr_spare_size = hxge_rbr_spare_size;
15036349Sqs148142 
15046349Sqs148142 	if (hxge_port_rbr_spare_size % HXGE_RXDMA_POST_BATCH) {
15056349Sqs148142 		hxge_port_rbr_spare_size = (HXGE_RXDMA_POST_BATCH *
15066349Sqs148142 		    (hxge_port_rbr_spare_size / HXGE_RXDMA_POST_BATCH + 1));
15076349Sqs148142 	}
15086349Sqs148142 
15096349Sqs148142 	rx_buf_alloc_size = (hxgep->rx_default_block_size *
15106349Sqs148142 	    (hxge_port_rbr_size + hxge_port_rbr_spare_size));
15116349Sqs148142 
15126349Sqs148142 	/*
15136349Sqs148142 	 * Addresses of receive block ring, receive completion ring and the
15146349Sqs148142 	 * mailbox must be all cache-aligned (64 bytes).
15156349Sqs148142 	 */
15167618SMichael.Speer@Sun.COM 	rx_rbr_cntl_alloc_size = hxge_port_rbr_size + hxge_port_rbr_spare_size;
15177618SMichael.Speer@Sun.COM 	rx_rbr_cntl_alloc_size *= sizeof (rx_desc_t);
15187618SMichael.Speer@Sun.COM 	rx_rcr_cntl_alloc_size = sizeof (rcr_entry_t) * hxge_port_rcr_size;
15197618SMichael.Speer@Sun.COM 	rx_mbox_cntl_alloc_size = sizeof (rxdma_mailbox_t);
15206349Sqs148142 
15216349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_alloc_rx_mem_pool: "
15226349Sqs148142 	    "hxge_port_rbr_size = %d hxge_port_rbr_spare_size = %d "
15236349Sqs148142 	    "hxge_port_rcr_size = %d rx_cntl_alloc_size = %d",
15246349Sqs148142 	    hxge_port_rbr_size, hxge_port_rbr_spare_size,
15256349Sqs148142 	    hxge_port_rcr_size, rx_cntl_alloc_size));
15266349Sqs148142 
15276349Sqs148142 	hxgep->hxge_port_rbr_size = hxge_port_rbr_size;
15286349Sqs148142 	hxgep->hxge_port_rcr_size = hxge_port_rcr_size;
15296349Sqs148142 
15306349Sqs148142 	/*
15316349Sqs148142 	 * Allocate memory for receive buffers and descriptor rings. Replace
15326349Sqs148142 	 * allocation functions with interface functions provided by the
15336349Sqs148142 	 * partition manager when it is available.
15346349Sqs148142 	 */
15356349Sqs148142 	/*
15366349Sqs148142 	 * Allocate memory for the receive buffer blocks.
15376349Sqs148142 	 */
15386349Sqs148142 	for (i = 0; i < ndmas; i++) {
15396349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
15406349Sqs148142 		    " hxge_alloc_rx_mem_pool to alloc mem: "
15416349Sqs148142 		    " dma %d dma_buf_p %llx &dma_buf_p %llx",
15426349Sqs148142 		    i, dma_buf_p[i], &dma_buf_p[i]));
15436349Sqs148142 
15446349Sqs148142 		num_chunks[i] = 0;
15456349Sqs148142 
15466349Sqs148142 		status = hxge_alloc_rx_buf_dma(hxgep, st_rdc, &dma_buf_p[i],
15476349Sqs148142 		    rx_buf_alloc_size, hxgep->rx_default_block_size,
15486349Sqs148142 		    &num_chunks[i]);
15496349Sqs148142 		if (status != HXGE_OK) {
15506349Sqs148142 			break;
15516349Sqs148142 		}
15526349Sqs148142 
15536349Sqs148142 		st_rdc++;
15546349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
15556349Sqs148142 		    " hxge_alloc_rx_mem_pool DONE  alloc mem: "
15566349Sqs148142 		    "dma %d dma_buf_p %llx &dma_buf_p %llx", i,
15576349Sqs148142 		    dma_buf_p[i], &dma_buf_p[i]));
15586349Sqs148142 	}
15596349Sqs148142 
15606349Sqs148142 	if (i < ndmas) {
15616349Sqs148142 		goto hxge_alloc_rx_mem_fail1;
15626349Sqs148142 	}
15636349Sqs148142 
15646349Sqs148142 	/*
15656349Sqs148142 	 * Allocate memory for descriptor rings and mailbox.
15666349Sqs148142 	 */
15676349Sqs148142 	st_rdc = p_cfgp->start_rdc;
15686349Sqs148142 	for (j = 0; j < ndmas; j++) {
15697618SMichael.Speer@Sun.COM 		if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc,
15707618SMichael.Speer@Sun.COM 		    &dma_rbr_cntl_p[j], &hxge_rx_rbr_desc_dma_attr,
15717618SMichael.Speer@Sun.COM 		    rx_rbr_cntl_alloc_size)) != HXGE_OK) {
15727618SMichael.Speer@Sun.COM 			break;
15737618SMichael.Speer@Sun.COM 		}
15747618SMichael.Speer@Sun.COM 
15757618SMichael.Speer@Sun.COM 		if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc,
15767618SMichael.Speer@Sun.COM 		    &dma_rcr_cntl_p[j], &hxge_rx_rcr_desc_dma_attr,
15777618SMichael.Speer@Sun.COM 		    rx_rcr_cntl_alloc_size)) != HXGE_OK) {
15787618SMichael.Speer@Sun.COM 			break;
15797618SMichael.Speer@Sun.COM 		}
15807618SMichael.Speer@Sun.COM 
15817618SMichael.Speer@Sun.COM 		if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc,
15827618SMichael.Speer@Sun.COM 		    &dma_mbox_cntl_p[j], &hxge_rx_mbox_dma_attr,
15837618SMichael.Speer@Sun.COM 		    rx_mbox_cntl_alloc_size)) != HXGE_OK) {
15846349Sqs148142 			break;
15856349Sqs148142 		}
15866349Sqs148142 		st_rdc++;
15876349Sqs148142 	}
15886349Sqs148142 
15896349Sqs148142 	if (j < ndmas) {
15906349Sqs148142 		goto hxge_alloc_rx_mem_fail2;
15916349Sqs148142 	}
15926349Sqs148142 
15936349Sqs148142 	dma_poolp->ndmas = ndmas;
15946349Sqs148142 	dma_poolp->num_chunks = num_chunks;
15956349Sqs148142 	dma_poolp->buf_allocated = B_TRUE;
15966349Sqs148142 	hxgep->rx_buf_pool_p = dma_poolp;
15976349Sqs148142 	dma_poolp->dma_buf_pool_p = dma_buf_p;
15986349Sqs148142 
15997618SMichael.Speer@Sun.COM 	dma_rbr_cntl_poolp->ndmas = ndmas;
16007618SMichael.Speer@Sun.COM 	dma_rbr_cntl_poolp->buf_allocated = B_TRUE;
16017618SMichael.Speer@Sun.COM 	hxgep->rx_rbr_cntl_pool_p = dma_rbr_cntl_poolp;
16027618SMichael.Speer@Sun.COM 	dma_rbr_cntl_poolp->dma_buf_pool_p = dma_rbr_cntl_p;
16037618SMichael.Speer@Sun.COM 
16047618SMichael.Speer@Sun.COM 	dma_rcr_cntl_poolp->ndmas = ndmas;
16057618SMichael.Speer@Sun.COM 	dma_rcr_cntl_poolp->buf_allocated = B_TRUE;
16067618SMichael.Speer@Sun.COM 	hxgep->rx_rcr_cntl_pool_p = dma_rcr_cntl_poolp;
16077618SMichael.Speer@Sun.COM 	dma_rcr_cntl_poolp->dma_buf_pool_p = dma_rcr_cntl_p;
16087618SMichael.Speer@Sun.COM 
16097618SMichael.Speer@Sun.COM 	dma_mbox_cntl_poolp->ndmas = ndmas;
16107618SMichael.Speer@Sun.COM 	dma_mbox_cntl_poolp->buf_allocated = B_TRUE;
16117618SMichael.Speer@Sun.COM 	hxgep->rx_mbox_cntl_pool_p = dma_mbox_cntl_poolp;
16127618SMichael.Speer@Sun.COM 	dma_mbox_cntl_poolp->dma_buf_pool_p = dma_mbox_cntl_p;
16136349Sqs148142 
16146349Sqs148142 	goto hxge_alloc_rx_mem_pool_exit;
16156349Sqs148142 
16166349Sqs148142 hxge_alloc_rx_mem_fail2:
16176349Sqs148142 	/* Free control buffers */
16186349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16196349Sqs148142 	    "==> hxge_alloc_rx_mem_pool: freeing control bufs (%d)", j));
16206349Sqs148142 	for (; j >= 0; j--) {
16216349Sqs148142 		hxge_free_rx_cntl_dma(hxgep,
16227618SMichael.Speer@Sun.COM 		    (p_hxge_dma_common_t)dma_rbr_cntl_p[j]);
16237618SMichael.Speer@Sun.COM 		hxge_free_rx_cntl_dma(hxgep,
16247618SMichael.Speer@Sun.COM 		    (p_hxge_dma_common_t)dma_rcr_cntl_p[j]);
16257618SMichael.Speer@Sun.COM 		hxge_free_rx_cntl_dma(hxgep,
16267618SMichael.Speer@Sun.COM 		    (p_hxge_dma_common_t)dma_mbox_cntl_p[j]);
16276349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16286349Sqs148142 		    "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
16296349Sqs148142 	}
16306349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16316349Sqs148142 	    "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
16326349Sqs148142 
16336349Sqs148142 hxge_alloc_rx_mem_fail1:
16346349Sqs148142 	/* Free data buffers */
16356349Sqs148142 	i--;
16366349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16376349Sqs148142 	    "==> hxge_alloc_rx_mem_pool: freeing data bufs (%d)", i));
16386349Sqs148142 	for (; i >= 0; i--) {
16396349Sqs148142 		hxge_free_rx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i],
16406349Sqs148142 		    num_chunks[i]);
16416349Sqs148142 	}
16426349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16436349Sqs148142 	    "==> hxge_alloc_rx_mem_pool: data bufs freed (%d)", i));
16446349Sqs148142 
16456349Sqs148142 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
16466349Sqs148142 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
16476349Sqs148142 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
16487618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_rbr_cntl_poolp, sizeof (hxge_dma_pool_t));
16497618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_rbr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
16507618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_rcr_cntl_poolp, sizeof (hxge_dma_pool_t));
16517618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_rcr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
16527618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_mbox_cntl_poolp, sizeof (hxge_dma_pool_t));
16537618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_mbox_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
16546349Sqs148142 
16556349Sqs148142 hxge_alloc_rx_mem_pool_exit:
16566349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16576349Sqs148142 	    "<== hxge_alloc_rx_mem_pool:status 0x%08x", status));
16586349Sqs148142 
16596349Sqs148142 	return (status);
16606349Sqs148142 }
16616349Sqs148142 
16626349Sqs148142 static void
hxge_free_rx_mem_pool(p_hxge_t hxgep)16636349Sqs148142 hxge_free_rx_mem_pool(p_hxge_t hxgep)
16646349Sqs148142 {
16656349Sqs148142 	uint32_t		i, ndmas;
16666349Sqs148142 	p_hxge_dma_pool_t	dma_poolp;
16676349Sqs148142 	p_hxge_dma_common_t	*dma_buf_p;
16687618SMichael.Speer@Sun.COM 	p_hxge_dma_pool_t	dma_rbr_cntl_poolp;
16697618SMichael.Speer@Sun.COM 	p_hxge_dma_common_t	*dma_rbr_cntl_p;
16707618SMichael.Speer@Sun.COM 	p_hxge_dma_pool_t	dma_rcr_cntl_poolp;
16717618SMichael.Speer@Sun.COM 	p_hxge_dma_common_t	*dma_rcr_cntl_p;
16727618SMichael.Speer@Sun.COM 	p_hxge_dma_pool_t	dma_mbox_cntl_poolp;
16737618SMichael.Speer@Sun.COM 	p_hxge_dma_common_t	*dma_mbox_cntl_p;
16746349Sqs148142 	uint32_t		*num_chunks;
16756349Sqs148142 
16766349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_free_rx_mem_pool"));
16776349Sqs148142 
16786349Sqs148142 	dma_poolp = hxgep->rx_buf_pool_p;
16796349Sqs148142 	if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
16806349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool "
16816349Sqs148142 		    "(null rx buf pool or buf not allocated"));
16826349Sqs148142 		return;
16836349Sqs148142 	}
16846349Sqs148142 
16857618SMichael.Speer@Sun.COM 	dma_rbr_cntl_poolp = hxgep->rx_rbr_cntl_pool_p;
16867618SMichael.Speer@Sun.COM 	if (dma_rbr_cntl_poolp == NULL ||
16877618SMichael.Speer@Sun.COM 	    (!dma_rbr_cntl_poolp->buf_allocated)) {
16886349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
16896349Sqs148142 		    "<== hxge_free_rx_mem_pool "
16907618SMichael.Speer@Sun.COM 		    "(null rbr cntl buf pool or rbr cntl buf not allocated"));
16917618SMichael.Speer@Sun.COM 		return;
16927618SMichael.Speer@Sun.COM 	}
16937618SMichael.Speer@Sun.COM 
16947618SMichael.Speer@Sun.COM 	dma_rcr_cntl_poolp = hxgep->rx_rcr_cntl_pool_p;
16957618SMichael.Speer@Sun.COM 	if (dma_rcr_cntl_poolp == NULL ||
16967618SMichael.Speer@Sun.COM 	    (!dma_rcr_cntl_poolp->buf_allocated)) {
16977618SMichael.Speer@Sun.COM 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
16987618SMichael.Speer@Sun.COM 		    "<== hxge_free_rx_mem_pool "
16997618SMichael.Speer@Sun.COM 		    "(null rcr cntl buf pool or rcr cntl buf not allocated"));
17007618SMichael.Speer@Sun.COM 		return;
17017618SMichael.Speer@Sun.COM 	}
17027618SMichael.Speer@Sun.COM 
17037618SMichael.Speer@Sun.COM 	dma_mbox_cntl_poolp = hxgep->rx_mbox_cntl_pool_p;
17047618SMichael.Speer@Sun.COM 	if (dma_mbox_cntl_poolp == NULL ||
17057618SMichael.Speer@Sun.COM 	    (!dma_mbox_cntl_poolp->buf_allocated)) {
17067618SMichael.Speer@Sun.COM 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
17077618SMichael.Speer@Sun.COM 		    "<== hxge_free_rx_mem_pool "
17087618SMichael.Speer@Sun.COM 		    "(null mbox cntl buf pool or mbox cntl buf not allocated"));
17096349Sqs148142 		return;
17106349Sqs148142 	}
17116349Sqs148142 
17126349Sqs148142 	dma_buf_p = dma_poolp->dma_buf_pool_p;
17136349Sqs148142 	num_chunks = dma_poolp->num_chunks;
17146349Sqs148142 
17157618SMichael.Speer@Sun.COM 	dma_rbr_cntl_p = dma_rbr_cntl_poolp->dma_buf_pool_p;
17167618SMichael.Speer@Sun.COM 	dma_rcr_cntl_p = dma_rcr_cntl_poolp->dma_buf_pool_p;
17177618SMichael.Speer@Sun.COM 	dma_mbox_cntl_p = dma_mbox_cntl_poolp->dma_buf_pool_p;
17187618SMichael.Speer@Sun.COM 	ndmas = dma_rbr_cntl_poolp->ndmas;
17196349Sqs148142 
17206349Sqs148142 	for (i = 0; i < ndmas; i++) {
17216349Sqs148142 		hxge_free_rx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]);
17226349Sqs148142 	}
17236349Sqs148142 
17246349Sqs148142 	for (i = 0; i < ndmas; i++) {
17257618SMichael.Speer@Sun.COM 		hxge_free_rx_cntl_dma(hxgep, dma_rbr_cntl_p[i]);
17267618SMichael.Speer@Sun.COM 		hxge_free_rx_cntl_dma(hxgep, dma_rcr_cntl_p[i]);
17277618SMichael.Speer@Sun.COM 		hxge_free_rx_cntl_dma(hxgep, dma_mbox_cntl_p[i]);
17286349Sqs148142 	}
17296349Sqs148142 
17306349Sqs148142 	for (i = 0; i < ndmas; i++) {
17316349Sqs148142 		KMEM_FREE(dma_buf_p[i],
17326349Sqs148142 		    sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
17337618SMichael.Speer@Sun.COM 		KMEM_FREE(dma_rbr_cntl_p[i], sizeof (hxge_dma_common_t));
17347618SMichael.Speer@Sun.COM 		KMEM_FREE(dma_rcr_cntl_p[i], sizeof (hxge_dma_common_t));
17357618SMichael.Speer@Sun.COM 		KMEM_FREE(dma_mbox_cntl_p[i], sizeof (hxge_dma_common_t));
17366349Sqs148142 	}
17376349Sqs148142 
17386349Sqs148142 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
17397618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_rbr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
17407618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_rbr_cntl_poolp, sizeof (hxge_dma_pool_t));
17417618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_rcr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
17427618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_rcr_cntl_poolp, sizeof (hxge_dma_pool_t));
17437618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_mbox_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
17447618SMichael.Speer@Sun.COM 	KMEM_FREE(dma_mbox_cntl_poolp, sizeof (hxge_dma_pool_t));
17456349Sqs148142 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
17466349Sqs148142 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
17476349Sqs148142 
17486349Sqs148142 	hxgep->rx_buf_pool_p = NULL;
17497618SMichael.Speer@Sun.COM 	hxgep->rx_rbr_cntl_pool_p = NULL;
17507618SMichael.Speer@Sun.COM 	hxgep->rx_rcr_cntl_pool_p = NULL;
17517618SMichael.Speer@Sun.COM 	hxgep->rx_mbox_cntl_pool_p = NULL;
17526349Sqs148142 
17536349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool"));
17546349Sqs148142 }
17556349Sqs148142 
17566349Sqs148142 static hxge_status_t
hxge_alloc_rx_buf_dma(p_hxge_t hxgep,uint16_t dma_channel,p_hxge_dma_common_t * dmap,size_t alloc_size,size_t block_size,uint32_t * num_chunks)17576349Sqs148142 hxge_alloc_rx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel,
17586349Sqs148142     p_hxge_dma_common_t *dmap,
17596349Sqs148142     size_t alloc_size, size_t block_size, uint32_t *num_chunks)
17606349Sqs148142 {
17616349Sqs148142 	p_hxge_dma_common_t	rx_dmap;
17626349Sqs148142 	hxge_status_t		status = HXGE_OK;
17636349Sqs148142 	size_t			total_alloc_size;
17646349Sqs148142 	size_t			allocated = 0;
17656349Sqs148142 	int			i, size_index, array_size;
17666349Sqs148142 
17676349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_buf_dma"));
17686349Sqs148142 
17696349Sqs148142 	rx_dmap = (p_hxge_dma_common_t)
17706349Sqs148142 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP);
17716349Sqs148142 
17726349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
17736349Sqs148142 	    " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ",
17746349Sqs148142 	    dma_channel, alloc_size, block_size, dmap));
17756349Sqs148142 
17766349Sqs148142 	total_alloc_size = alloc_size;
17776349Sqs148142 
17786349Sqs148142 	i = 0;
17796349Sqs148142 	size_index = 0;
17806349Sqs148142 	array_size = sizeof (alloc_sizes) / sizeof (size_t);
17818141SMichael.Speer@Sun.COM 	while ((size_index < array_size) &&
17828141SMichael.Speer@Sun.COM 	    (alloc_sizes[size_index] < alloc_size))
17836349Sqs148142 		size_index++;
17846349Sqs148142 	if (size_index >= array_size) {
17856349Sqs148142 		size_index = array_size - 1;
17866349Sqs148142 	}
17876349Sqs148142 
17886349Sqs148142 	while ((allocated < total_alloc_size) &&
17896349Sqs148142 	    (size_index >= 0) && (i < HXGE_DMA_BLOCK)) {
17906349Sqs148142 		rx_dmap[i].dma_chunk_index = i;
17916349Sqs148142 		rx_dmap[i].block_size = block_size;
17926349Sqs148142 		rx_dmap[i].alength = alloc_sizes[size_index];
17936349Sqs148142 		rx_dmap[i].orig_alength = rx_dmap[i].alength;
17946349Sqs148142 		rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
17956349Sqs148142 		rx_dmap[i].dma_channel = dma_channel;
17966349Sqs148142 		rx_dmap[i].contig_alloc_type = B_FALSE;
17976349Sqs148142 
17986349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
17996349Sqs148142 		    "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x "
18006349Sqs148142 		    "i %d nblocks %d alength %d",
18016349Sqs148142 		    dma_channel, i, &rx_dmap[i], block_size,
18026349Sqs148142 		    i, rx_dmap[i].nblocks, rx_dmap[i].alength));
18036349Sqs148142 		status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
18046349Sqs148142 		    &hxge_rx_dma_attr, rx_dmap[i].alength,
18056349Sqs148142 		    &hxge_dev_buf_dma_acc_attr,
18066349Sqs148142 		    DDI_DMA_READ | DDI_DMA_STREAMING,
18076349Sqs148142 		    (p_hxge_dma_common_t)(&rx_dmap[i]));
18086349Sqs148142 		if (status != HXGE_OK) {
18096349Sqs148142 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
18106349Sqs148142 			    " hxge_alloc_rx_buf_dma: Alloc Failed: "
18116349Sqs148142 			    " for size: %d", alloc_sizes[size_index]));
18126349Sqs148142 			size_index--;
18136349Sqs148142 		} else {
18146349Sqs148142 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
18156349Sqs148142 			    " alloc_rx_buf_dma allocated rdc %d "
18166349Sqs148142 			    "chunk %d size %x dvma %x bufp %llx ",
18176349Sqs148142 			    dma_channel, i, rx_dmap[i].alength,
18186349Sqs148142 			    rx_dmap[i].ioaddr_pp, &rx_dmap[i]));
18196349Sqs148142 			i++;
18206349Sqs148142 			allocated += alloc_sizes[size_index];
18216349Sqs148142 		}
18226349Sqs148142 	}
18236349Sqs148142 
18246349Sqs148142 	if (allocated < total_alloc_size) {
18256349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
18266349Sqs148142 		    " hxge_alloc_rx_buf_dma failed due to"
18276349Sqs148142 		    " allocated(%d) < required(%d)",
18286349Sqs148142 		    allocated, total_alloc_size));
18296349Sqs148142 		goto hxge_alloc_rx_mem_fail1;
18306349Sqs148142 	}
18316349Sqs148142 
18326349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
18336349Sqs148142 	    " alloc_rx_buf_dma rdc %d allocated %d chunks", dma_channel, i));
18346349Sqs148142 
18356349Sqs148142 	*num_chunks = i;
18366349Sqs148142 	*dmap = rx_dmap;
18376349Sqs148142 
18386349Sqs148142 	goto hxge_alloc_rx_mem_exit;
18396349Sqs148142 
18406349Sqs148142 hxge_alloc_rx_mem_fail1:
18416349Sqs148142 	KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
18426349Sqs148142 
18436349Sqs148142 hxge_alloc_rx_mem_exit:
18446349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
18456349Sqs148142 	    "<== hxge_alloc_rx_buf_dma status 0x%08x", status));
18466349Sqs148142 
18476349Sqs148142 	return (status);
18486349Sqs148142 }
18496349Sqs148142 
18506349Sqs148142 /*ARGSUSED*/
18516349Sqs148142 static void
hxge_free_rx_buf_dma(p_hxge_t hxgep,p_hxge_dma_common_t dmap,uint32_t num_chunks)18526349Sqs148142 hxge_free_rx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap,
18536349Sqs148142     uint32_t num_chunks)
18546349Sqs148142 {
18556349Sqs148142 	int i;
18566349Sqs148142 
18576349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
18586349Sqs148142 	    "==> hxge_free_rx_buf_dma: # of chunks %d", num_chunks));
18596349Sqs148142 
18606349Sqs148142 	for (i = 0; i < num_chunks; i++) {
18616349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
18626349Sqs148142 		    "==> hxge_free_rx_buf_dma: chunk %d dmap 0x%llx", i, dmap));
18636349Sqs148142 		hxge_dma_mem_free(dmap++);
18646349Sqs148142 	}
18656349Sqs148142 
18666349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_buf_dma"));
18676349Sqs148142 }
18686349Sqs148142 
18696349Sqs148142 /*ARGSUSED*/
18706349Sqs148142 static hxge_status_t
hxge_alloc_rx_cntl_dma(p_hxge_t hxgep,uint16_t dma_channel,p_hxge_dma_common_t * dmap,struct ddi_dma_attr * attr,size_t size)18716349Sqs148142 hxge_alloc_rx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel,
18727618SMichael.Speer@Sun.COM     p_hxge_dma_common_t *dmap, struct ddi_dma_attr *attr, size_t size)
18736349Sqs148142 {
18746349Sqs148142 	p_hxge_dma_common_t	rx_dmap;
18756349Sqs148142 	hxge_status_t		status = HXGE_OK;
18766349Sqs148142 
18776349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_cntl_dma"));
18786349Sqs148142 
18796349Sqs148142 	rx_dmap = (p_hxge_dma_common_t)
18806349Sqs148142 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t), KM_SLEEP);
18816349Sqs148142 
18826349Sqs148142 	rx_dmap->contig_alloc_type = B_FALSE;
18836349Sqs148142 
18846349Sqs148142 	status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
18857618SMichael.Speer@Sun.COM 	    attr, size, &hxge_dev_desc_dma_acc_attr,
18866349Sqs148142 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, rx_dmap);
18876349Sqs148142 	if (status != HXGE_OK) {
18886349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
18896349Sqs148142 		    " hxge_alloc_rx_cntl_dma: Alloc Failed: "
18906349Sqs148142 		    " for size: %d", size));
18916349Sqs148142 		goto hxge_alloc_rx_cntl_dma_fail1;
18926349Sqs148142 	}
18936349Sqs148142 
18946349Sqs148142 	*dmap = rx_dmap;
18956349Sqs148142 
18966349Sqs148142 	goto hxge_alloc_rx_cntl_dma_exit;
18976349Sqs148142 
18986349Sqs148142 hxge_alloc_rx_cntl_dma_fail1:
18996349Sqs148142 	KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t));
19006349Sqs148142 
19016349Sqs148142 hxge_alloc_rx_cntl_dma_exit:
19026349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
19036349Sqs148142 	    "<== hxge_alloc_rx_cntl_dma status 0x%08x", status));
19046349Sqs148142 
19056349Sqs148142 	return (status);
19066349Sqs148142 }
19076349Sqs148142 
19086349Sqs148142 /*ARGSUSED*/
19096349Sqs148142 static void
hxge_free_rx_cntl_dma(p_hxge_t hxgep,p_hxge_dma_common_t dmap)19106349Sqs148142 hxge_free_rx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap)
19116349Sqs148142 {
19126349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_rx_cntl_dma"));
19136349Sqs148142 
19146349Sqs148142 	hxge_dma_mem_free(dmap);
19156349Sqs148142 
19166349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_rx_cntl_dma"));
19176349Sqs148142 }
19186349Sqs148142 
19196349Sqs148142 static hxge_status_t
hxge_alloc_tx_mem_pool(p_hxge_t hxgep)19206349Sqs148142 hxge_alloc_tx_mem_pool(p_hxge_t hxgep)
19216349Sqs148142 {
19226349Sqs148142 	hxge_status_t		status = HXGE_OK;
19236349Sqs148142 	int			i, j;
19246349Sqs148142 	uint32_t		ndmas, st_tdc;
19256349Sqs148142 	p_hxge_dma_pt_cfg_t	p_all_cfgp;
19266349Sqs148142 	p_hxge_hw_pt_cfg_t	p_cfgp;
19276349Sqs148142 	p_hxge_dma_pool_t	dma_poolp;
19286349Sqs148142 	p_hxge_dma_common_t	*dma_buf_p;
19296349Sqs148142 	p_hxge_dma_pool_t	dma_cntl_poolp;
19306349Sqs148142 	p_hxge_dma_common_t	*dma_cntl_p;
19316349Sqs148142 	size_t			tx_buf_alloc_size;
19326349Sqs148142 	size_t			tx_cntl_alloc_size;
19336349Sqs148142 	uint32_t		*num_chunks;	/* per dma */
19346349Sqs148142 
19356349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool"));
19366349Sqs148142 
19376349Sqs148142 	p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
19386349Sqs148142 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
19396349Sqs148142 	st_tdc = p_cfgp->start_tdc;
19406349Sqs148142 	ndmas = p_cfgp->max_tdcs;
19416349Sqs148142 
19426349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool: "
19436349Sqs148142 	    "p_cfgp 0x%016llx start_tdc %d ndmas %d hxgep->max_tdcs %d",
19446349Sqs148142 	    p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, hxgep->max_tdcs));
19456349Sqs148142 	/*
19466349Sqs148142 	 * Allocate memory for each transmit DMA channel.
19476349Sqs148142 	 */
19486349Sqs148142 	dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t),
19496349Sqs148142 	    KM_SLEEP);
19506349Sqs148142 	dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
19516349Sqs148142 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
19526349Sqs148142 
19536349Sqs148142 	dma_cntl_poolp = (p_hxge_dma_pool_t)
19546349Sqs148142 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
19556349Sqs148142 	dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
19566349Sqs148142 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
19576349Sqs148142 
19586349Sqs148142 	hxgep->hxge_port_tx_ring_size = hxge_tx_ring_size;
19596349Sqs148142 
19606349Sqs148142 	/*
19616349Sqs148142 	 * Assume that each DMA channel will be configured with default
19626349Sqs148142 	 * transmit bufer size for copying transmit data. (For packet payload
19636349Sqs148142 	 * over this limit, packets will not be copied.)
19646349Sqs148142 	 */
19656349Sqs148142 	tx_buf_alloc_size = (hxge_bcopy_thresh * hxge_tx_ring_size);
19666349Sqs148142 
19676349Sqs148142 	/*
19686349Sqs148142 	 * Addresses of transmit descriptor ring and the mailbox must be all
19696349Sqs148142 	 * cache-aligned (64 bytes).
19706349Sqs148142 	 */
19716349Sqs148142 	tx_cntl_alloc_size = hxge_tx_ring_size;
19726349Sqs148142 	tx_cntl_alloc_size *= (sizeof (tx_desc_t));
19736349Sqs148142 	tx_cntl_alloc_size += sizeof (txdma_mailbox_t);
19746349Sqs148142 
19756349Sqs148142 	num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas,
19766349Sqs148142 	    KM_SLEEP);
19776349Sqs148142 
19786349Sqs148142 	/*
19796349Sqs148142 	 * Allocate memory for transmit buffers and descriptor rings. Replace
19806349Sqs148142 	 * allocation functions with interface functions provided by the
19816349Sqs148142 	 * partition manager when it is available.
19826349Sqs148142 	 *
19836349Sqs148142 	 * Allocate memory for the transmit buffer pool.
19846349Sqs148142 	 */
19856349Sqs148142 	for (i = 0; i < ndmas; i++) {
19866349Sqs148142 		num_chunks[i] = 0;
19876349Sqs148142 		status = hxge_alloc_tx_buf_dma(hxgep, st_tdc, &dma_buf_p[i],
19886349Sqs148142 		    tx_buf_alloc_size, hxge_bcopy_thresh, &num_chunks[i]);
19896349Sqs148142 		if (status != HXGE_OK) {
19906349Sqs148142 			break;
19916349Sqs148142 		}
19926349Sqs148142 		st_tdc++;
19936349Sqs148142 	}
19946349Sqs148142 
19956349Sqs148142 	if (i < ndmas) {
19966349Sqs148142 		goto hxge_alloc_tx_mem_pool_fail1;
19976349Sqs148142 	}
19986349Sqs148142 
19996349Sqs148142 	st_tdc = p_cfgp->start_tdc;
20006349Sqs148142 
20016349Sqs148142 	/*
20026349Sqs148142 	 * Allocate memory for descriptor rings and mailbox.
20036349Sqs148142 	 */
20046349Sqs148142 	for (j = 0; j < ndmas; j++) {
20056349Sqs148142 		status = hxge_alloc_tx_cntl_dma(hxgep, st_tdc, &dma_cntl_p[j],
20066349Sqs148142 		    tx_cntl_alloc_size);
20076349Sqs148142 		if (status != HXGE_OK) {
20086349Sqs148142 			break;
20096349Sqs148142 		}
20106349Sqs148142 		st_tdc++;
20116349Sqs148142 	}
20126349Sqs148142 
20136349Sqs148142 	if (j < ndmas) {
20146349Sqs148142 		goto hxge_alloc_tx_mem_pool_fail2;
20156349Sqs148142 	}
20166349Sqs148142 
20176349Sqs148142 	dma_poolp->ndmas = ndmas;
20186349Sqs148142 	dma_poolp->num_chunks = num_chunks;
20196349Sqs148142 	dma_poolp->buf_allocated = B_TRUE;
20206349Sqs148142 	dma_poolp->dma_buf_pool_p = dma_buf_p;
20216349Sqs148142 	hxgep->tx_buf_pool_p = dma_poolp;
20226349Sqs148142 
20236349Sqs148142 	dma_cntl_poolp->ndmas = ndmas;
20246349Sqs148142 	dma_cntl_poolp->buf_allocated = B_TRUE;
20256349Sqs148142 	dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
20266349Sqs148142 	hxgep->tx_cntl_pool_p = dma_cntl_poolp;
20276349Sqs148142 
20286349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM_CTL,
20296349Sqs148142 	    "==> hxge_alloc_tx_mem_pool: start_tdc %d "
20306349Sqs148142 	    "ndmas %d poolp->ndmas %d", st_tdc, ndmas, dma_poolp->ndmas));
20316349Sqs148142 
20326349Sqs148142 	goto hxge_alloc_tx_mem_pool_exit;
20336349Sqs148142 
20346349Sqs148142 hxge_alloc_tx_mem_pool_fail2:
20356349Sqs148142 	/* Free control buffers */
20366349Sqs148142 	j--;
20376349Sqs148142 	for (; j >= 0; j--) {
20386349Sqs148142 		hxge_free_tx_cntl_dma(hxgep,
20396349Sqs148142 		    (p_hxge_dma_common_t)dma_cntl_p[j]);
20406349Sqs148142 	}
20416349Sqs148142 
20426349Sqs148142 hxge_alloc_tx_mem_pool_fail1:
20436349Sqs148142 	/* Free data buffers */
20446349Sqs148142 	i--;
20456349Sqs148142 	for (; i >= 0; i--) {
20466349Sqs148142 		hxge_free_tx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i],
20476349Sqs148142 		    num_chunks[i]);
20486349Sqs148142 	}
20496349Sqs148142 
20506349Sqs148142 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
20516349Sqs148142 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
20526349Sqs148142 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
20536349Sqs148142 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
20546349Sqs148142 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
20556349Sqs148142 
20566349Sqs148142 hxge_alloc_tx_mem_pool_exit:
20576349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM_CTL,
20586349Sqs148142 	    "<== hxge_alloc_tx_mem_pool:status 0x%08x", status));
20596349Sqs148142 
20606349Sqs148142 	return (status);
20616349Sqs148142 }
20626349Sqs148142 
20636349Sqs148142 static hxge_status_t
hxge_alloc_tx_buf_dma(p_hxge_t hxgep,uint16_t dma_channel,p_hxge_dma_common_t * dmap,size_t alloc_size,size_t block_size,uint32_t * num_chunks)20646349Sqs148142 hxge_alloc_tx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel,
20656349Sqs148142     p_hxge_dma_common_t *dmap, size_t alloc_size,
20666349Sqs148142     size_t block_size, uint32_t *num_chunks)
20676349Sqs148142 {
20686349Sqs148142 	p_hxge_dma_common_t	tx_dmap;
20696349Sqs148142 	hxge_status_t		status = HXGE_OK;
20706349Sqs148142 	size_t			total_alloc_size;
20716349Sqs148142 	size_t			allocated = 0;
20726349Sqs148142 	int			i, size_index, array_size;
20736349Sqs148142 
20746349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_buf_dma"));
20756349Sqs148142 
20766349Sqs148142 	tx_dmap = (p_hxge_dma_common_t)
20776349Sqs148142 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP);
20786349Sqs148142 
20796349Sqs148142 	total_alloc_size = alloc_size;
20806349Sqs148142 	i = 0;
20816349Sqs148142 	size_index = 0;
20826349Sqs148142 	array_size = sizeof (alloc_sizes) / sizeof (size_t);
20838141SMichael.Speer@Sun.COM 	while ((size_index < array_size) &&
20848141SMichael.Speer@Sun.COM 	    (alloc_sizes[size_index] < alloc_size))
20856349Sqs148142 		size_index++;
20866349Sqs148142 	if (size_index >= array_size) {
20876349Sqs148142 		size_index = array_size - 1;
20886349Sqs148142 	}
20896349Sqs148142 
20906349Sqs148142 	while ((allocated < total_alloc_size) &&
20916349Sqs148142 	    (size_index >= 0) && (i < HXGE_DMA_BLOCK)) {
20926349Sqs148142 		tx_dmap[i].dma_chunk_index = i;
20936349Sqs148142 		tx_dmap[i].block_size = block_size;
20946349Sqs148142 		tx_dmap[i].alength = alloc_sizes[size_index];
20956349Sqs148142 		tx_dmap[i].orig_alength = tx_dmap[i].alength;
20966349Sqs148142 		tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
20976349Sqs148142 		tx_dmap[i].dma_channel = dma_channel;
20986349Sqs148142 		tx_dmap[i].contig_alloc_type = B_FALSE;
20996349Sqs148142 
21006349Sqs148142 		status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
21016349Sqs148142 		    &hxge_tx_dma_attr, tx_dmap[i].alength,
21026349Sqs148142 		    &hxge_dev_buf_dma_acc_attr,
21036349Sqs148142 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
21046349Sqs148142 		    (p_hxge_dma_common_t)(&tx_dmap[i]));
21056349Sqs148142 		if (status != HXGE_OK) {
21066349Sqs148142 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
21076349Sqs148142 			    " hxge_alloc_tx_buf_dma: Alloc Failed: "
21086349Sqs148142 			    " for size: %d", alloc_sizes[size_index]));
21096349Sqs148142 			size_index--;
21106349Sqs148142 		} else {
21116349Sqs148142 			i++;
21126349Sqs148142 			allocated += alloc_sizes[size_index];
21136349Sqs148142 		}
21146349Sqs148142 	}
21156349Sqs148142 
21166349Sqs148142 	if (allocated < total_alloc_size) {
21176349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
21186349Sqs148142 		    " hxge_alloc_tx_buf_dma: failed due to"
21196349Sqs148142 		    " allocated(%d) < required(%d)",
21206349Sqs148142 		    allocated, total_alloc_size));
21216349Sqs148142 		goto hxge_alloc_tx_mem_fail1;
21226349Sqs148142 	}
21236349Sqs148142 
21246349Sqs148142 	*num_chunks = i;
21256349Sqs148142 	*dmap = tx_dmap;
21266349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
21276349Sqs148142 	    "==> hxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d",
21286349Sqs148142 	    *dmap, i));
21296349Sqs148142 	goto hxge_alloc_tx_mem_exit;
21306349Sqs148142 
21316349Sqs148142 hxge_alloc_tx_mem_fail1:
21326349Sqs148142 	KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
21336349Sqs148142 
21346349Sqs148142 hxge_alloc_tx_mem_exit:
21356349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
21366349Sqs148142 	    "<== hxge_alloc_tx_buf_dma status 0x%08x", status));
21376349Sqs148142 
21386349Sqs148142 	return (status);
21396349Sqs148142 }
21406349Sqs148142 
21416349Sqs148142 /*ARGSUSED*/
21426349Sqs148142 static void
hxge_free_tx_buf_dma(p_hxge_t hxgep,p_hxge_dma_common_t dmap,uint32_t num_chunks)21436349Sqs148142 hxge_free_tx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap,
21446349Sqs148142     uint32_t num_chunks)
21456349Sqs148142 {
21466349Sqs148142 	int i;
21476349Sqs148142 
21486349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_tx_buf_dma"));
21496349Sqs148142 
21506349Sqs148142 	for (i = 0; i < num_chunks; i++) {
21516349Sqs148142 		hxge_dma_mem_free(dmap++);
21526349Sqs148142 	}
21536349Sqs148142 
21546349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_tx_buf_dma"));
21556349Sqs148142 }
21566349Sqs148142 
21576349Sqs148142 /*ARGSUSED*/
21586349Sqs148142 static hxge_status_t
hxge_alloc_tx_cntl_dma(p_hxge_t hxgep,uint16_t dma_channel,p_hxge_dma_common_t * dmap,size_t size)21596349Sqs148142 hxge_alloc_tx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel,
21606349Sqs148142     p_hxge_dma_common_t *dmap, size_t size)
21616349Sqs148142 {
21626349Sqs148142 	p_hxge_dma_common_t	tx_dmap;
21636349Sqs148142 	hxge_status_t		status = HXGE_OK;
21646349Sqs148142 
21656349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_cntl_dma"));
21666349Sqs148142 
21676349Sqs148142 	tx_dmap = (p_hxge_dma_common_t)KMEM_ZALLOC(sizeof (hxge_dma_common_t),
21686349Sqs148142 	    KM_SLEEP);
21696349Sqs148142 
21706349Sqs148142 	tx_dmap->contig_alloc_type = B_FALSE;
21716349Sqs148142 
21726349Sqs148142 	status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
21737618SMichael.Speer@Sun.COM 	    &hxge_tx_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr,
21746349Sqs148142 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, tx_dmap);
21756349Sqs148142 	if (status != HXGE_OK) {
21766349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
21776349Sqs148142 		    " hxge_alloc_tx_cntl_dma: Alloc Failed: "
21786349Sqs148142 		    " for size: %d", size));
21796349Sqs148142 		goto hxge_alloc_tx_cntl_dma_fail1;
21806349Sqs148142 	}
21816349Sqs148142 
21826349Sqs148142 	*dmap = tx_dmap;
21836349Sqs148142 
21846349Sqs148142 	goto hxge_alloc_tx_cntl_dma_exit;
21856349Sqs148142 
21866349Sqs148142 hxge_alloc_tx_cntl_dma_fail1:
21876349Sqs148142 	KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t));
21886349Sqs148142 
21896349Sqs148142 hxge_alloc_tx_cntl_dma_exit:
21906349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
21916349Sqs148142 	    "<== hxge_alloc_tx_cntl_dma status 0x%08x", status));
21926349Sqs148142 
21936349Sqs148142 	return (status);
21946349Sqs148142 }
21956349Sqs148142 
21966349Sqs148142 /*ARGSUSED*/
21976349Sqs148142 static void
hxge_free_tx_cntl_dma(p_hxge_t hxgep,p_hxge_dma_common_t dmap)21986349Sqs148142 hxge_free_tx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap)
21996349Sqs148142 {
22006349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_tx_cntl_dma"));
22016349Sqs148142 
22026349Sqs148142 	hxge_dma_mem_free(dmap);
22036349Sqs148142 
22046349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_tx_cntl_dma"));
22056349Sqs148142 }
22066349Sqs148142 
22076349Sqs148142 static void
hxge_free_tx_mem_pool(p_hxge_t hxgep)22086349Sqs148142 hxge_free_tx_mem_pool(p_hxge_t hxgep)
22096349Sqs148142 {
22106349Sqs148142 	uint32_t		i, ndmas;
22116349Sqs148142 	p_hxge_dma_pool_t	dma_poolp;
22126349Sqs148142 	p_hxge_dma_common_t	*dma_buf_p;
22136349Sqs148142 	p_hxge_dma_pool_t	dma_cntl_poolp;
22146349Sqs148142 	p_hxge_dma_common_t	*dma_cntl_p;
22156349Sqs148142 	uint32_t		*num_chunks;
22166349Sqs148142 
22176349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "==> hxge_free_tx_mem_pool"));
22186349Sqs148142 
22196349Sqs148142 	dma_poolp = hxgep->tx_buf_pool_p;
22206349Sqs148142 	if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
22216349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MEM3_CTL,
22226349Sqs148142 		    "<== hxge_free_tx_mem_pool "
22236349Sqs148142 		    "(null rx buf pool or buf not allocated"));
22246349Sqs148142 		return;
22256349Sqs148142 	}
22266349Sqs148142 
22276349Sqs148142 	dma_cntl_poolp = hxgep->tx_cntl_pool_p;
22286349Sqs148142 	if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
22296349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MEM3_CTL,
22306349Sqs148142 		    "<== hxge_free_tx_mem_pool "
22316349Sqs148142 		    "(null tx cntl buf pool or cntl buf not allocated"));
22326349Sqs148142 		return;
22336349Sqs148142 	}
22346349Sqs148142 
22356349Sqs148142 	dma_buf_p = dma_poolp->dma_buf_pool_p;
22366349Sqs148142 	num_chunks = dma_poolp->num_chunks;
22376349Sqs148142 
22386349Sqs148142 	dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
22396349Sqs148142 	ndmas = dma_cntl_poolp->ndmas;
22406349Sqs148142 
22416349Sqs148142 	for (i = 0; i < ndmas; i++) {
22426349Sqs148142 		hxge_free_tx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]);
22436349Sqs148142 	}
22446349Sqs148142 
22456349Sqs148142 	for (i = 0; i < ndmas; i++) {
22466349Sqs148142 		hxge_free_tx_cntl_dma(hxgep, dma_cntl_p[i]);
22476349Sqs148142 	}
22486349Sqs148142 
22496349Sqs148142 	for (i = 0; i < ndmas; i++) {
22506349Sqs148142 		KMEM_FREE(dma_buf_p[i],
22516349Sqs148142 		    sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
22526349Sqs148142 		KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t));
22536349Sqs148142 	}
22546349Sqs148142 
22556349Sqs148142 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
22566349Sqs148142 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
22576349Sqs148142 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
22586349Sqs148142 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
22596349Sqs148142 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
22606349Sqs148142 
22616349Sqs148142 	hxgep->tx_buf_pool_p = NULL;
22626349Sqs148142 	hxgep->tx_cntl_pool_p = NULL;
22636349Sqs148142 
22646349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "<== hxge_free_tx_mem_pool"));
22656349Sqs148142 }
22666349Sqs148142 
22676349Sqs148142 /*ARGSUSED*/
22686349Sqs148142 static hxge_status_t
hxge_dma_mem_alloc(p_hxge_t hxgep,dma_method_t method,struct ddi_dma_attr * dma_attrp,size_t length,ddi_device_acc_attr_t * acc_attr_p,uint_t xfer_flags,p_hxge_dma_common_t dma_p)22696349Sqs148142 hxge_dma_mem_alloc(p_hxge_t hxgep, dma_method_t method,
22706349Sqs148142     struct ddi_dma_attr *dma_attrp,
22716349Sqs148142     size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags,
22726349Sqs148142     p_hxge_dma_common_t dma_p)
22736349Sqs148142 {
22746349Sqs148142 	caddr_t		kaddrp;
22756349Sqs148142 	int		ddi_status = DDI_SUCCESS;
22766349Sqs148142 
22776349Sqs148142 	dma_p->dma_handle = NULL;
22786349Sqs148142 	dma_p->acc_handle = NULL;
22796349Sqs148142 	dma_p->kaddrp = NULL;
22806349Sqs148142 
22816349Sqs148142 	ddi_status = ddi_dma_alloc_handle(hxgep->dip, dma_attrp,
22826349Sqs148142 	    DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle);
22836349Sqs148142 	if (ddi_status != DDI_SUCCESS) {
22846349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
22856349Sqs148142 		    "hxge_dma_mem_alloc:ddi_dma_alloc_handle failed."));
22866349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
22876349Sqs148142 	}
22886349Sqs148142 
22896349Sqs148142 	ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, acc_attr_p,
22906349Sqs148142 	    xfer_flags, DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength,
22916349Sqs148142 	    &dma_p->acc_handle);
22926349Sqs148142 	if (ddi_status != DDI_SUCCESS) {
22936349Sqs148142 		/* The caller will decide whether it is fatal */
22946349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
22956349Sqs148142 		    "hxge_dma_mem_alloc:ddi_dma_mem_alloc failed"));
22966349Sqs148142 		ddi_dma_free_handle(&dma_p->dma_handle);
22976349Sqs148142 		dma_p->dma_handle = NULL;
22986349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
22996349Sqs148142 	}
23006349Sqs148142 
23016349Sqs148142 	if (dma_p->alength < length) {
23026349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
23036349Sqs148142 		    "hxge_dma_mem_alloc:ddi_dma_mem_alloc < length."));
23046349Sqs148142 		ddi_dma_mem_free(&dma_p->acc_handle);
23056349Sqs148142 		ddi_dma_free_handle(&dma_p->dma_handle);
23066349Sqs148142 		dma_p->acc_handle = NULL;
23076349Sqs148142 		dma_p->dma_handle = NULL;
23086349Sqs148142 		return (HXGE_ERROR);
23096349Sqs148142 	}
23106349Sqs148142 
23116349Sqs148142 	ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
23126349Sqs148142 	    kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
23136349Sqs148142 	    &dma_p->dma_cookie, &dma_p->ncookies);
23146349Sqs148142 	if (ddi_status != DDI_DMA_MAPPED) {
23156349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
23166349Sqs148142 		    "hxge_dma_mem_alloc:di_dma_addr_bind failed "
23176349Sqs148142 		    "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies));
23186349Sqs148142 		if (dma_p->acc_handle) {
23196349Sqs148142 			ddi_dma_mem_free(&dma_p->acc_handle);
23206349Sqs148142 			dma_p->acc_handle = NULL;
23216349Sqs148142 		}
23226349Sqs148142 		ddi_dma_free_handle(&dma_p->dma_handle);
23236349Sqs148142 		dma_p->dma_handle = NULL;
23246349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
23256349Sqs148142 	}
23266349Sqs148142 
23276349Sqs148142 	if (dma_p->ncookies != 1) {
23286349Sqs148142 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
23296349Sqs148142 		    "hxge_dma_mem_alloc:ddi_dma_addr_bind > 1 cookie"
23306349Sqs148142 		    "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies));
23316349Sqs148142 		if (dma_p->acc_handle) {
23326349Sqs148142 			ddi_dma_mem_free(&dma_p->acc_handle);
23336349Sqs148142 			dma_p->acc_handle = NULL;
23346349Sqs148142 		}
23356349Sqs148142 		(void) ddi_dma_unbind_handle(dma_p->dma_handle);
23366349Sqs148142 		ddi_dma_free_handle(&dma_p->dma_handle);
23376349Sqs148142 		dma_p->dma_handle = NULL;
23386349Sqs148142 		return (HXGE_ERROR);
23396349Sqs148142 	}
23406349Sqs148142 
23416349Sqs148142 	dma_p->kaddrp = kaddrp;
23426349Sqs148142 #if defined(__i386)
23436349Sqs148142 	dma_p->ioaddr_pp =
23446349Sqs148142 	    (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress;
23456349Sqs148142 #else
23466349Sqs148142 	dma_p->ioaddr_pp = (unsigned char *) dma_p->dma_cookie.dmac_laddress;
23476349Sqs148142 #endif
23486349Sqs148142 
23496349Sqs148142 	HPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle);
23506349Sqs148142 
23516349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_dma_mem_alloc: "
23526349Sqs148142 	    "dma buffer allocated: dma_p $%p "
23536349Sqs148142 	    "return dmac_ladress from cookie $%p dmac_size %d "
23546349Sqs148142 	    "dma_p->ioaddr_p $%p "
23556349Sqs148142 	    "dma_p->orig_ioaddr_p $%p "
23566349Sqs148142 	    "orig_vatopa $%p "
23576349Sqs148142 	    "alength %d (0x%x) "
23586349Sqs148142 	    "kaddrp $%p "
23596349Sqs148142 	    "length %d (0x%x)",
23606349Sqs148142 	    dma_p,
23616349Sqs148142 	    dma_p->dma_cookie.dmac_laddress,
23626349Sqs148142 	    dma_p->dma_cookie.dmac_size,
23636349Sqs148142 	    dma_p->ioaddr_pp,
23646349Sqs148142 	    dma_p->orig_ioaddr_pp,
23656349Sqs148142 	    dma_p->orig_vatopa,
23666349Sqs148142 	    dma_p->alength, dma_p->alength,
23676349Sqs148142 	    kaddrp,
23686349Sqs148142 	    length, length));
23696349Sqs148142 
23706349Sqs148142 	return (HXGE_OK);
23716349Sqs148142 }
23726349Sqs148142 
23736349Sqs148142 static void
hxge_dma_mem_free(p_hxge_dma_common_t dma_p)23746349Sqs148142 hxge_dma_mem_free(p_hxge_dma_common_t dma_p)
23756349Sqs148142 {
23767618SMichael.Speer@Sun.COM 	if (dma_p == NULL)
23777618SMichael.Speer@Sun.COM 		return;
23787618SMichael.Speer@Sun.COM 
23796349Sqs148142 	if (dma_p->dma_handle != NULL) {
23806349Sqs148142 		if (dma_p->ncookies) {
23816349Sqs148142 			(void) ddi_dma_unbind_handle(dma_p->dma_handle);
23826349Sqs148142 			dma_p->ncookies = 0;
23836349Sqs148142 		}
23846349Sqs148142 		ddi_dma_free_handle(&dma_p->dma_handle);
23856349Sqs148142 		dma_p->dma_handle = NULL;
23866349Sqs148142 	}
23877618SMichael.Speer@Sun.COM 
23886349Sqs148142 	if (dma_p->acc_handle != NULL) {
23896349Sqs148142 		ddi_dma_mem_free(&dma_p->acc_handle);
23906349Sqs148142 		dma_p->acc_handle = NULL;
23916349Sqs148142 		HPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
23926349Sqs148142 	}
23937618SMichael.Speer@Sun.COM 
23946349Sqs148142 	dma_p->kaddrp = NULL;
23956349Sqs148142 	dma_p->alength = NULL;
23966349Sqs148142 }
23976349Sqs148142 
23986349Sqs148142 /*
23996349Sqs148142  *	hxge_m_start() -- start transmitting and receiving.
24006349Sqs148142  *
24016349Sqs148142  *	This function is called by the MAC layer when the first
24026349Sqs148142  *	stream is open to prepare the hardware ready for sending
24036349Sqs148142  *	and transmitting packets.
24046349Sqs148142  */
24056349Sqs148142 static int
hxge_m_start(void * arg)24066349Sqs148142 hxge_m_start(void *arg)
24076349Sqs148142 {
24086349Sqs148142 	p_hxge_t hxgep = (p_hxge_t)arg;
24096349Sqs148142 
24106349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_start"));
24116349Sqs148142 
24126349Sqs148142 	MUTEX_ENTER(hxgep->genlock);
24136349Sqs148142 
24146349Sqs148142 	if (hxge_init(hxgep) != DDI_SUCCESS) {
24156349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
24166349Sqs148142 		    "<== hxge_m_start: initialization failed"));
24176349Sqs148142 		MUTEX_EXIT(hxgep->genlock);
24186349Sqs148142 		return (EIO);
24196349Sqs148142 	}
24206349Sqs148142 
24216349Sqs148142 	if (hxgep->hxge_mac_state != HXGE_MAC_STARTED) {
24226349Sqs148142 		/*
24236349Sqs148142 		 * Start timer to check the system error and tx hangs
24246349Sqs148142 		 */
24256349Sqs148142 		hxgep->hxge_timerid = hxge_start_timer(hxgep,
24266349Sqs148142 		    hxge_check_hw_state, HXGE_CHECK_TIMER);
24276349Sqs148142 
24286349Sqs148142 		hxgep->hxge_mac_state = HXGE_MAC_STARTED;
24297949SQiyan.Sun@Sun.COM 
24307949SQiyan.Sun@Sun.COM 		hxgep->timeout.link_status = 0;
24317949SQiyan.Sun@Sun.COM 		hxgep->timeout.report_link_status = B_TRUE;
24327949SQiyan.Sun@Sun.COM 		hxgep->timeout.ticks = drv_usectohz(2 * 1000000);
24337949SQiyan.Sun@Sun.COM 
24347949SQiyan.Sun@Sun.COM 		/* Start the link status timer to check the link status */
24357949SQiyan.Sun@Sun.COM 		MUTEX_ENTER(&hxgep->timeout.lock);
24367949SQiyan.Sun@Sun.COM 		hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep,
24377949SQiyan.Sun@Sun.COM 		    hxgep->timeout.ticks);
24387949SQiyan.Sun@Sun.COM 		MUTEX_EXIT(&hxgep->timeout.lock);
24396349Sqs148142 	}
24406349Sqs148142 
24416349Sqs148142 	MUTEX_EXIT(hxgep->genlock);
24426349Sqs148142 
24436349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_start"));
24446349Sqs148142 
24456349Sqs148142 	return (0);
24466349Sqs148142 }
24476349Sqs148142 
24486349Sqs148142 /*
24496349Sqs148142  * hxge_m_stop(): stop transmitting and receiving.
24506349Sqs148142  */
24516349Sqs148142 static void
hxge_m_stop(void * arg)24526349Sqs148142 hxge_m_stop(void *arg)
24536349Sqs148142 {
24546349Sqs148142 	p_hxge_t hxgep = (p_hxge_t)arg;
24556349Sqs148142 
24566349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_stop"));
24576349Sqs148142 
24586349Sqs148142 	if (hxgep->hxge_timerid) {
24596349Sqs148142 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
24606349Sqs148142 		hxgep->hxge_timerid = 0;
24616349Sqs148142 	}
24626349Sqs148142 
24637949SQiyan.Sun@Sun.COM 	/* Stop the link status timer before unregistering */
24647949SQiyan.Sun@Sun.COM 	MUTEX_ENTER(&hxgep->timeout.lock);
24657949SQiyan.Sun@Sun.COM 	if (hxgep->timeout.id) {
24667949SQiyan.Sun@Sun.COM 		(void) untimeout(hxgep->timeout.id);
24677949SQiyan.Sun@Sun.COM 		hxgep->timeout.id = 0;
24687949SQiyan.Sun@Sun.COM 	}
24697949SQiyan.Sun@Sun.COM 	hxge_link_update(hxgep, LINK_STATE_DOWN);
24707949SQiyan.Sun@Sun.COM 	MUTEX_EXIT(&hxgep->timeout.lock);
24717949SQiyan.Sun@Sun.COM 
24726349Sqs148142 	MUTEX_ENTER(hxgep->genlock);
24736349Sqs148142 
24746349Sqs148142 	hxge_uninit(hxgep);
24756349Sqs148142 
24766349Sqs148142 	hxgep->hxge_mac_state = HXGE_MAC_STOPPED;
24776349Sqs148142 
24786349Sqs148142 	MUTEX_EXIT(hxgep->genlock);
24796349Sqs148142 
24806349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_stop"));
24816349Sqs148142 }
24826349Sqs148142 
24836349Sqs148142 static int
hxge_m_multicst(void * arg,boolean_t add,const uint8_t * mca)24846349Sqs148142 hxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
24856349Sqs148142 {
24866349Sqs148142 	p_hxge_t		hxgep = (p_hxge_t)arg;
24876349Sqs148142 	struct ether_addr	addrp;
24886349Sqs148142 
24896349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_multicst: add %d", add));
24906349Sqs148142 
24916349Sqs148142 	bcopy(mca, (uint8_t *)&addrp, ETHERADDRL);
24926349Sqs148142 
24936349Sqs148142 	if (add) {
24946349Sqs148142 		if (hxge_add_mcast_addr(hxgep, &addrp)) {
24956349Sqs148142 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
24966349Sqs148142 			    "<== hxge_m_multicst: add multicast failed"));
24976349Sqs148142 			return (EINVAL);
24986349Sqs148142 		}
24996349Sqs148142 	} else {
25006349Sqs148142 		if (hxge_del_mcast_addr(hxgep, &addrp)) {
25016349Sqs148142 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
25026349Sqs148142 			    "<== hxge_m_multicst: del multicast failed"));
25036349Sqs148142 			return (EINVAL);
25046349Sqs148142 		}
25056349Sqs148142 	}
25066349Sqs148142 
25076349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_multicst"));
25086349Sqs148142 
25096349Sqs148142 	return (0);
25106349Sqs148142 }
25116349Sqs148142 
25126349Sqs148142 static int
hxge_m_promisc(void * arg,boolean_t on)25136349Sqs148142 hxge_m_promisc(void *arg, boolean_t on)
25146349Sqs148142 {
25156349Sqs148142 	p_hxge_t hxgep = (p_hxge_t)arg;
25166349Sqs148142 
25176349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_promisc: on %d", on));
25186349Sqs148142 
25196349Sqs148142 	if (hxge_set_promisc(hxgep, on)) {
25206349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
25216349Sqs148142 		    "<== hxge_m_promisc: set promisc failed"));
25226349Sqs148142 		return (EINVAL);
25236349Sqs148142 	}
25246349Sqs148142 
25256349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_promisc: on %d", on));
25266349Sqs148142 
25276349Sqs148142 	return (0);
25286349Sqs148142 }
25296349Sqs148142 
25306349Sqs148142 static void
hxge_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)25316349Sqs148142 hxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
25326349Sqs148142 {
25336349Sqs148142 	p_hxge_t	hxgep = (p_hxge_t)arg;
25346349Sqs148142 	struct iocblk	*iocp = (struct iocblk *)mp->b_rptr;
25356349Sqs148142 	boolean_t	need_privilege;
25366349Sqs148142 	int		err;
25376349Sqs148142 	int		cmd;
25386349Sqs148142 
25396349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl"));
25406349Sqs148142 
25416349Sqs148142 	iocp = (struct iocblk *)mp->b_rptr;
25426349Sqs148142 	iocp->ioc_error = 0;
25436349Sqs148142 	need_privilege = B_TRUE;
25446349Sqs148142 	cmd = iocp->ioc_cmd;
25456349Sqs148142 
25466349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl: cmd 0x%08x", cmd));
25476349Sqs148142 	switch (cmd) {
25486349Sqs148142 	default:
25496349Sqs148142 		miocnak(wq, mp, 0, EINVAL);
25506349Sqs148142 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl: invalid"));
25516349Sqs148142 		return;
25526349Sqs148142 
25536349Sqs148142 	case LB_GET_INFO_SIZE:
25546349Sqs148142 	case LB_GET_INFO:
25556349Sqs148142 	case LB_GET_MODE:
25566349Sqs148142 		need_privilege = B_FALSE;
25576349Sqs148142 		break;
25586349Sqs148142 
25596349Sqs148142 	case LB_SET_MODE:
25606349Sqs148142 		break;
25616349Sqs148142 
25626349Sqs148142 	case ND_GET:
25636349Sqs148142 		need_privilege = B_FALSE;
25646349Sqs148142 		break;
25656349Sqs148142 	case ND_SET:
25666349Sqs148142 		break;
25676349Sqs148142 
25686349Sqs148142 	case HXGE_GET_TX_RING_SZ:
25696349Sqs148142 	case HXGE_GET_TX_DESC:
25706349Sqs148142 	case HXGE_TX_SIDE_RESET:
25716349Sqs148142 	case HXGE_RX_SIDE_RESET:
25726349Sqs148142 	case HXGE_GLOBAL_RESET:
25736349Sqs148142 	case HXGE_RESET_MAC:
25746349Sqs148142 	case HXGE_PUT_TCAM:
25756349Sqs148142 	case HXGE_GET_TCAM:
25766349Sqs148142 	case HXGE_RTRACE:
25776349Sqs148142 
25786349Sqs148142 		need_privilege = B_FALSE;
25796349Sqs148142 		break;
25806349Sqs148142 	}
25816349Sqs148142 
25826349Sqs148142 	if (need_privilege) {
25836349Sqs148142 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
25846349Sqs148142 		if (err != 0) {
25856349Sqs148142 			miocnak(wq, mp, 0, err);
25866349Sqs148142 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
25876349Sqs148142 			    "<== hxge_m_ioctl: no priv"));
25886349Sqs148142 			return;
25896349Sqs148142 		}
25906349Sqs148142 	}
25916349Sqs148142 
25926349Sqs148142 	switch (cmd) {
25936349Sqs148142 	case ND_GET:
25946349Sqs148142 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_GET command"));
25956349Sqs148142 	case ND_SET:
25966349Sqs148142 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_SET command"));
25976349Sqs148142 		hxge_param_ioctl(hxgep, wq, mp, iocp);
25986349Sqs148142 		break;
25996349Sqs148142 
26006349Sqs148142 	case LB_GET_MODE:
26016349Sqs148142 	case LB_SET_MODE:
26026349Sqs148142 	case LB_GET_INFO_SIZE:
26036349Sqs148142 	case LB_GET_INFO:
26046349Sqs148142 		hxge_loopback_ioctl(hxgep, wq, mp, iocp);
26056349Sqs148142 		break;
26066349Sqs148142 
26076349Sqs148142 	case HXGE_PUT_TCAM:
26086349Sqs148142 	case HXGE_GET_TCAM:
26096349Sqs148142 	case HXGE_GET_TX_RING_SZ:
26106349Sqs148142 	case HXGE_GET_TX_DESC:
26116349Sqs148142 	case HXGE_TX_SIDE_RESET:
26126349Sqs148142 	case HXGE_RX_SIDE_RESET:
26136349Sqs148142 	case HXGE_GLOBAL_RESET:
26146349Sqs148142 	case HXGE_RESET_MAC:
26156349Sqs148142 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL,
26166349Sqs148142 		    "==> hxge_m_ioctl: cmd 0x%x", cmd));
26176349Sqs148142 		hxge_hw_ioctl(hxgep, wq, mp, iocp);
26186349Sqs148142 		break;
26196349Sqs148142 	}
26206349Sqs148142 
26216349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl"));
26226349Sqs148142 }
26236349Sqs148142 
26246349Sqs148142 /*ARGSUSED*/
26258718SMichael.Speer@Sun.COM static int
hxge_tx_ring_start(mac_ring_driver_t rdriver,uint64_t mr_gen_num)26268718SMichael.Speer@Sun.COM hxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num)
26278718SMichael.Speer@Sun.COM {
26288718SMichael.Speer@Sun.COM 	p_hxge_ring_handle_t	rhp = (p_hxge_ring_handle_t)rdriver;
26298718SMichael.Speer@Sun.COM 	p_hxge_t		hxgep;
26308718SMichael.Speer@Sun.COM 	p_tx_ring_t		ring;
26318718SMichael.Speer@Sun.COM 
26328718SMichael.Speer@Sun.COM 	ASSERT(rhp != NULL);
26338718SMichael.Speer@Sun.COM 	ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
26348718SMichael.Speer@Sun.COM 
26358718SMichael.Speer@Sun.COM 	hxgep = rhp->hxgep;
26368718SMichael.Speer@Sun.COM 
26378718SMichael.Speer@Sun.COM 	/*
26388718SMichael.Speer@Sun.COM 	 * Get the ring pointer.
26398718SMichael.Speer@Sun.COM 	 */
26408718SMichael.Speer@Sun.COM 	ring = hxgep->tx_rings->rings[rhp->index];
26418718SMichael.Speer@Sun.COM 
26428718SMichael.Speer@Sun.COM 	/*
26438718SMichael.Speer@Sun.COM 	 * Fill in the handle for the transmit.
26448718SMichael.Speer@Sun.COM 	 */
26458718SMichael.Speer@Sun.COM 	MUTEX_ENTER(&ring->lock);
264610091SMichael.Speer@Sun.COM 	rhp->started = B_TRUE;
26478718SMichael.Speer@Sun.COM 	ring->ring_handle = rhp->ring_handle;
26488718SMichael.Speer@Sun.COM 	MUTEX_EXIT(&ring->lock);
26498718SMichael.Speer@Sun.COM 
26508718SMichael.Speer@Sun.COM 	return (0);
26518718SMichael.Speer@Sun.COM }
26528718SMichael.Speer@Sun.COM 
26538718SMichael.Speer@Sun.COM static void
hxge_tx_ring_stop(mac_ring_driver_t rdriver)26548718SMichael.Speer@Sun.COM hxge_tx_ring_stop(mac_ring_driver_t rdriver)
26558718SMichael.Speer@Sun.COM {
26568718SMichael.Speer@Sun.COM 	p_hxge_ring_handle_t    rhp = (p_hxge_ring_handle_t)rdriver;
26578718SMichael.Speer@Sun.COM 	p_hxge_t		hxgep;
26588718SMichael.Speer@Sun.COM 	p_tx_ring_t		ring;
26598718SMichael.Speer@Sun.COM 
26608718SMichael.Speer@Sun.COM 	ASSERT(rhp != NULL);
26618718SMichael.Speer@Sun.COM 	ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
26628718SMichael.Speer@Sun.COM 
26638718SMichael.Speer@Sun.COM 	hxgep = rhp->hxgep;
26648718SMichael.Speer@Sun.COM 	ring = hxgep->tx_rings->rings[rhp->index];
26658718SMichael.Speer@Sun.COM 
26668718SMichael.Speer@Sun.COM 	MUTEX_ENTER(&ring->lock);
26678718SMichael.Speer@Sun.COM 	ring->ring_handle = (mac_ring_handle_t)NULL;
266810091SMichael.Speer@Sun.COM 	rhp->started = B_FALSE;
26698718SMichael.Speer@Sun.COM 	MUTEX_EXIT(&ring->lock);
26708718SMichael.Speer@Sun.COM }
26718718SMichael.Speer@Sun.COM 
26728718SMichael.Speer@Sun.COM static int
hxge_rx_ring_start(mac_ring_driver_t rdriver,uint64_t mr_gen_num)26738718SMichael.Speer@Sun.COM hxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num)
26748718SMichael.Speer@Sun.COM {
26758718SMichael.Speer@Sun.COM 	p_hxge_ring_handle_t	rhp = (p_hxge_ring_handle_t)rdriver;
26768718SMichael.Speer@Sun.COM 	p_hxge_t		hxgep;
26778718SMichael.Speer@Sun.COM 	p_rx_rcr_ring_t		ring;
26788718SMichael.Speer@Sun.COM 	int			i;
26798718SMichael.Speer@Sun.COM 
26808718SMichael.Speer@Sun.COM 	ASSERT(rhp != NULL);
26818718SMichael.Speer@Sun.COM 	ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
26828718SMichael.Speer@Sun.COM 
26838718SMichael.Speer@Sun.COM 	hxgep = rhp->hxgep;
26848718SMichael.Speer@Sun.COM 
26858718SMichael.Speer@Sun.COM 	/*
26868718SMichael.Speer@Sun.COM 	 * Get pointer to ring.
26878718SMichael.Speer@Sun.COM 	 */
26888718SMichael.Speer@Sun.COM 	ring = hxgep->rx_rcr_rings->rcr_rings[rhp->index];
26898718SMichael.Speer@Sun.COM 
26908718SMichael.Speer@Sun.COM 	MUTEX_ENTER(&ring->lock);
26918718SMichael.Speer@Sun.COM 
26928718SMichael.Speer@Sun.COM 	if (rhp->started) {
26938718SMichael.Speer@Sun.COM 		MUTEX_EXIT(&ring->lock);
26948718SMichael.Speer@Sun.COM 		return (0);
26958718SMichael.Speer@Sun.COM 	}
26968718SMichael.Speer@Sun.COM 
26978718SMichael.Speer@Sun.COM 	/*
26988718SMichael.Speer@Sun.COM 	 * Set the ldvp and ldgp pointers to enable/disable
26998718SMichael.Speer@Sun.COM 	 * polling.
27008718SMichael.Speer@Sun.COM 	 */
27018718SMichael.Speer@Sun.COM 	for (i = 0; i < hxgep->ldgvp->maxldvs; i++) {
27028718SMichael.Speer@Sun.COM 		if ((hxgep->ldgvp->ldvp[i].is_rxdma == 1) &&
27038718SMichael.Speer@Sun.COM 		    (hxgep->ldgvp->ldvp[i].channel == rhp->index)) {
27048718SMichael.Speer@Sun.COM 			ring->ldvp = &hxgep->ldgvp->ldvp[i];
27058718SMichael.Speer@Sun.COM 			ring->ldgp = hxgep->ldgvp->ldvp[i].ldgp;
27068718SMichael.Speer@Sun.COM 			break;
27078718SMichael.Speer@Sun.COM 		}
27088718SMichael.Speer@Sun.COM 	}
27098718SMichael.Speer@Sun.COM 
27108718SMichael.Speer@Sun.COM 	rhp->started = B_TRUE;
27118718SMichael.Speer@Sun.COM 	ring->rcr_mac_handle = rhp->ring_handle;
27128718SMichael.Speer@Sun.COM 	ring->rcr_gen_num = mr_gen_num;
27138718SMichael.Speer@Sun.COM 	MUTEX_EXIT(&ring->lock);
27148718SMichael.Speer@Sun.COM 
27158718SMichael.Speer@Sun.COM 	return (0);
27168718SMichael.Speer@Sun.COM }
27178718SMichael.Speer@Sun.COM 
27188718SMichael.Speer@Sun.COM static void
hxge_rx_ring_stop(mac_ring_driver_t rdriver)27198718SMichael.Speer@Sun.COM hxge_rx_ring_stop(mac_ring_driver_t rdriver)
27208718SMichael.Speer@Sun.COM {
27218718SMichael.Speer@Sun.COM 	p_hxge_ring_handle_t	rhp = (p_hxge_ring_handle_t)rdriver;
27228718SMichael.Speer@Sun.COM 	p_hxge_t		hxgep;
27238718SMichael.Speer@Sun.COM 	p_rx_rcr_ring_t		ring;
27248718SMichael.Speer@Sun.COM 
27258718SMichael.Speer@Sun.COM 	ASSERT(rhp != NULL);
27268718SMichael.Speer@Sun.COM 	ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
27278718SMichael.Speer@Sun.COM 
27288718SMichael.Speer@Sun.COM 	hxgep = rhp->hxgep;
27298718SMichael.Speer@Sun.COM 	ring =  hxgep->rx_rcr_rings->rcr_rings[rhp->index];
27308718SMichael.Speer@Sun.COM 
27318718SMichael.Speer@Sun.COM 	MUTEX_ENTER(&ring->lock);
27328718SMichael.Speer@Sun.COM 	rhp->started = B_TRUE;
27338718SMichael.Speer@Sun.COM 	ring->rcr_mac_handle = NULL;
27348718SMichael.Speer@Sun.COM 	ring->ldvp = NULL;
27358718SMichael.Speer@Sun.COM 	ring->ldgp = NULL;
27368718SMichael.Speer@Sun.COM 	MUTEX_EXIT(&ring->lock);
27378718SMichael.Speer@Sun.COM }
27388718SMichael.Speer@Sun.COM 
27398718SMichael.Speer@Sun.COM static int
hxge_rx_group_start(mac_group_driver_t gdriver)27408718SMichael.Speer@Sun.COM hxge_rx_group_start(mac_group_driver_t gdriver)
27418718SMichael.Speer@Sun.COM {
27428718SMichael.Speer@Sun.COM 	hxge_ring_group_t	*group = (hxge_ring_group_t *)gdriver;
27438718SMichael.Speer@Sun.COM 
27448718SMichael.Speer@Sun.COM 	ASSERT(group->hxgep != NULL);
27458718SMichael.Speer@Sun.COM 	ASSERT(group->hxgep->hxge_mac_state == HXGE_MAC_STARTED);
27468718SMichael.Speer@Sun.COM 
27478718SMichael.Speer@Sun.COM 	MUTEX_ENTER(group->hxgep->genlock);
27488718SMichael.Speer@Sun.COM 	group->started = B_TRUE;
27498718SMichael.Speer@Sun.COM 	MUTEX_EXIT(group->hxgep->genlock);
27508718SMichael.Speer@Sun.COM 
27518718SMichael.Speer@Sun.COM 	return (0);
27528718SMichael.Speer@Sun.COM }
27538718SMichael.Speer@Sun.COM 
27548718SMichael.Speer@Sun.COM static void
hxge_rx_group_stop(mac_group_driver_t gdriver)27558718SMichael.Speer@Sun.COM hxge_rx_group_stop(mac_group_driver_t gdriver)
27568718SMichael.Speer@Sun.COM {
27578718SMichael.Speer@Sun.COM 	hxge_ring_group_t	*group = (hxge_ring_group_t *)gdriver;
27588718SMichael.Speer@Sun.COM 
27598718SMichael.Speer@Sun.COM 	ASSERT(group->hxgep != NULL);
27608718SMichael.Speer@Sun.COM 	ASSERT(group->hxgep->hxge_mac_state == HXGE_MAC_STARTED);
27618718SMichael.Speer@Sun.COM 	ASSERT(group->started == B_TRUE);
27628718SMichael.Speer@Sun.COM 
27638718SMichael.Speer@Sun.COM 	MUTEX_ENTER(group->hxgep->genlock);
27648718SMichael.Speer@Sun.COM 	group->started = B_FALSE;
27658718SMichael.Speer@Sun.COM 	MUTEX_EXIT(group->hxgep->genlock);
27668718SMichael.Speer@Sun.COM }
27678718SMichael.Speer@Sun.COM 
27688718SMichael.Speer@Sun.COM static int
hxge_mmac_get_slot(p_hxge_t hxgep,int * slot)27698718SMichael.Speer@Sun.COM hxge_mmac_get_slot(p_hxge_t hxgep, int *slot)
27708718SMichael.Speer@Sun.COM {
27718718SMichael.Speer@Sun.COM 	int	i;
27728718SMichael.Speer@Sun.COM 
27738718SMichael.Speer@Sun.COM 	/*
27748718SMichael.Speer@Sun.COM 	 * Find an open slot.
27758718SMichael.Speer@Sun.COM 	 */
27768718SMichael.Speer@Sun.COM 	for (i = 0; i < hxgep->mmac.total; i++) {
27778718SMichael.Speer@Sun.COM 		if (!hxgep->mmac.addrs[i].set) {
27788718SMichael.Speer@Sun.COM 			*slot = i;
27798718SMichael.Speer@Sun.COM 			return (0);
27808718SMichael.Speer@Sun.COM 		}
27818718SMichael.Speer@Sun.COM 	}
27828718SMichael.Speer@Sun.COM 
27838718SMichael.Speer@Sun.COM 	return (ENXIO);
27848718SMichael.Speer@Sun.COM }
27858718SMichael.Speer@Sun.COM 
27868718SMichael.Speer@Sun.COM static int
hxge_mmac_set_addr(p_hxge_t hxgep,int slot,const uint8_t * addr)27878718SMichael.Speer@Sun.COM hxge_mmac_set_addr(p_hxge_t hxgep, int slot, const uint8_t *addr)
27888718SMichael.Speer@Sun.COM {
27898718SMichael.Speer@Sun.COM 	struct ether_addr	eaddr;
27908718SMichael.Speer@Sun.COM 	hxge_status_t		status = HXGE_OK;
27918718SMichael.Speer@Sun.COM 
27928718SMichael.Speer@Sun.COM 	bcopy(addr, (uint8_t *)&eaddr, ETHERADDRL);
27938718SMichael.Speer@Sun.COM 
27948718SMichael.Speer@Sun.COM 	/*
27958718SMichael.Speer@Sun.COM 	 * Set new interface local address and re-init device.
27968718SMichael.Speer@Sun.COM 	 * This is destructive to any other streams attached
27978718SMichael.Speer@Sun.COM 	 * to this device.
27988718SMichael.Speer@Sun.COM 	 */
27998718SMichael.Speer@Sun.COM 	RW_ENTER_WRITER(&hxgep->filter_lock);
28008718SMichael.Speer@Sun.COM 	status = hxge_pfc_set_mac_address(hxgep, slot, &eaddr);
28018718SMichael.Speer@Sun.COM 	RW_EXIT(&hxgep->filter_lock);
28028718SMichael.Speer@Sun.COM 	if (status != HXGE_OK)
28038718SMichael.Speer@Sun.COM 		return (status);
28048718SMichael.Speer@Sun.COM 
28058718SMichael.Speer@Sun.COM 	hxgep->mmac.addrs[slot].set = B_TRUE;
28068718SMichael.Speer@Sun.COM 	bcopy(addr, hxgep->mmac.addrs[slot].addr, ETHERADDRL);
28078718SMichael.Speer@Sun.COM 	hxgep->mmac.available--;
28088718SMichael.Speer@Sun.COM 	if (slot == HXGE_MAC_DEFAULT_ADDR_SLOT)
28098718SMichael.Speer@Sun.COM 		hxgep->mmac.addrs[slot].primary = B_TRUE;
28108718SMichael.Speer@Sun.COM 
28118718SMichael.Speer@Sun.COM 	return (0);
28128718SMichael.Speer@Sun.COM }
28138718SMichael.Speer@Sun.COM 
28148718SMichael.Speer@Sun.COM static int
hxge_mmac_find_addr(p_hxge_t hxgep,const uint8_t * addr,int * slot)28158718SMichael.Speer@Sun.COM hxge_mmac_find_addr(p_hxge_t hxgep, const uint8_t *addr, int *slot)
28168718SMichael.Speer@Sun.COM {
28178718SMichael.Speer@Sun.COM 	int	i, result;
28188718SMichael.Speer@Sun.COM 
28198718SMichael.Speer@Sun.COM 	for (i = 0; i < hxgep->mmac.total; i++) {
28208718SMichael.Speer@Sun.COM 		if (hxgep->mmac.addrs[i].set) {
28218718SMichael.Speer@Sun.COM 			result = memcmp(hxgep->mmac.addrs[i].addr,
28228718SMichael.Speer@Sun.COM 			    addr, ETHERADDRL);
28238718SMichael.Speer@Sun.COM 			if (result == 0) {
28248718SMichael.Speer@Sun.COM 				*slot = i;
28258718SMichael.Speer@Sun.COM 				return (0);
28268718SMichael.Speer@Sun.COM 			}
28278718SMichael.Speer@Sun.COM 		}
28288718SMichael.Speer@Sun.COM 	}
28298718SMichael.Speer@Sun.COM 
28308718SMichael.Speer@Sun.COM 	return (EINVAL);
28318718SMichael.Speer@Sun.COM }
28328718SMichael.Speer@Sun.COM 
28338718SMichael.Speer@Sun.COM static int
hxge_mmac_unset_addr(p_hxge_t hxgep,int slot)28348718SMichael.Speer@Sun.COM hxge_mmac_unset_addr(p_hxge_t hxgep, int slot)
28358718SMichael.Speer@Sun.COM {
28368718SMichael.Speer@Sun.COM 	hxge_status_t	status;
28378718SMichael.Speer@Sun.COM 	int		i;
28388718SMichael.Speer@Sun.COM 
28398718SMichael.Speer@Sun.COM 	status = hxge_pfc_clear_mac_address(hxgep, slot);
28408718SMichael.Speer@Sun.COM 	if (status != HXGE_OK)
28418718SMichael.Speer@Sun.COM 		return (status);
28428718SMichael.Speer@Sun.COM 
28438718SMichael.Speer@Sun.COM 	for (i = 0; i < ETHERADDRL; i++)
28448718SMichael.Speer@Sun.COM 		hxgep->mmac.addrs[slot].addr[i] = 0;
28458718SMichael.Speer@Sun.COM 
28468718SMichael.Speer@Sun.COM 	hxgep->mmac.addrs[slot].set = B_FALSE;
28478718SMichael.Speer@Sun.COM 	if (slot == HXGE_MAC_DEFAULT_ADDR_SLOT)
28488718SMichael.Speer@Sun.COM 		hxgep->mmac.addrs[slot].primary = B_FALSE;
28498718SMichael.Speer@Sun.COM 	hxgep->mmac.available++;
28508718SMichael.Speer@Sun.COM 
28518718SMichael.Speer@Sun.COM 	return (0);
28528718SMichael.Speer@Sun.COM }
28538718SMichael.Speer@Sun.COM 
28548718SMichael.Speer@Sun.COM static int
hxge_rx_group_add_mac(void * arg,const uint8_t * mac_addr)28558718SMichael.Speer@Sun.COM hxge_rx_group_add_mac(void *arg, const uint8_t *mac_addr)
28568718SMichael.Speer@Sun.COM {
28578718SMichael.Speer@Sun.COM 	hxge_ring_group_t	*group = arg;
28588718SMichael.Speer@Sun.COM 	p_hxge_t		hxgep = group->hxgep;
28598718SMichael.Speer@Sun.COM 	int			slot = 0;
28608718SMichael.Speer@Sun.COM 
28618718SMichael.Speer@Sun.COM 	ASSERT(group->type == MAC_RING_TYPE_RX);
28628718SMichael.Speer@Sun.COM 
28638718SMichael.Speer@Sun.COM 	MUTEX_ENTER(hxgep->genlock);
28648718SMichael.Speer@Sun.COM 
28658718SMichael.Speer@Sun.COM 	/*
28668718SMichael.Speer@Sun.COM 	 * Find a slot for the address.
28678718SMichael.Speer@Sun.COM 	 */
28688718SMichael.Speer@Sun.COM 	if (hxge_mmac_get_slot(hxgep, &slot) != 0) {
28698718SMichael.Speer@Sun.COM 		MUTEX_EXIT(hxgep->genlock);
28708718SMichael.Speer@Sun.COM 		return (ENOSPC);
28718718SMichael.Speer@Sun.COM 	}
28728718SMichael.Speer@Sun.COM 
28738718SMichael.Speer@Sun.COM 	/*
28748718SMichael.Speer@Sun.COM 	 * Program the MAC address.
28758718SMichael.Speer@Sun.COM 	 */
28768718SMichael.Speer@Sun.COM 	if (hxge_mmac_set_addr(hxgep, slot, mac_addr) != 0) {
28778718SMichael.Speer@Sun.COM 		MUTEX_EXIT(hxgep->genlock);
28788718SMichael.Speer@Sun.COM 		return (ENOSPC);
28798718SMichael.Speer@Sun.COM 	}
28808718SMichael.Speer@Sun.COM 
28818718SMichael.Speer@Sun.COM 	MUTEX_EXIT(hxgep->genlock);
28828718SMichael.Speer@Sun.COM 	return (0);
28838718SMichael.Speer@Sun.COM }
28848718SMichael.Speer@Sun.COM 
28858718SMichael.Speer@Sun.COM static int
hxge_rx_group_rem_mac(void * arg,const uint8_t * mac_addr)28868718SMichael.Speer@Sun.COM hxge_rx_group_rem_mac(void *arg, const uint8_t *mac_addr)
28878718SMichael.Speer@Sun.COM {
28888718SMichael.Speer@Sun.COM 	hxge_ring_group_t	*group = arg;
28898718SMichael.Speer@Sun.COM 	p_hxge_t		hxgep = group->hxgep;
28908718SMichael.Speer@Sun.COM 	int			rv, slot;
28918718SMichael.Speer@Sun.COM 
28928718SMichael.Speer@Sun.COM 	ASSERT(group->type == MAC_RING_TYPE_RX);
28938718SMichael.Speer@Sun.COM 
28948718SMichael.Speer@Sun.COM 	MUTEX_ENTER(hxgep->genlock);
28958718SMichael.Speer@Sun.COM 
28968718SMichael.Speer@Sun.COM 	if ((rv = hxge_mmac_find_addr(hxgep, mac_addr, &slot)) != 0) {
28978718SMichael.Speer@Sun.COM 		MUTEX_EXIT(hxgep->genlock);
28988718SMichael.Speer@Sun.COM 		return (rv);
28998718SMichael.Speer@Sun.COM 	}
29008718SMichael.Speer@Sun.COM 
29018718SMichael.Speer@Sun.COM 	if ((rv = hxge_mmac_unset_addr(hxgep, slot)) != 0) {
29028718SMichael.Speer@Sun.COM 		MUTEX_EXIT(hxgep->genlock);
29038718SMichael.Speer@Sun.COM 		return (rv);
29048718SMichael.Speer@Sun.COM 	}
29058718SMichael.Speer@Sun.COM 
29068718SMichael.Speer@Sun.COM 	MUTEX_EXIT(hxgep->genlock);
29078718SMichael.Speer@Sun.COM 	return (0);
29088718SMichael.Speer@Sun.COM }
29098718SMichael.Speer@Sun.COM 
29108718SMichael.Speer@Sun.COM static void
hxge_group_get(void * arg,mac_ring_type_t type,int groupid,mac_group_info_t * infop,mac_group_handle_t gh)29118718SMichael.Speer@Sun.COM hxge_group_get(void *arg, mac_ring_type_t type, int groupid,
29128718SMichael.Speer@Sun.COM     mac_group_info_t *infop, mac_group_handle_t gh)
29138718SMichael.Speer@Sun.COM {
29148718SMichael.Speer@Sun.COM 	p_hxge_t		hxgep = arg;
29158718SMichael.Speer@Sun.COM 	hxge_ring_group_t	*group;
29168718SMichael.Speer@Sun.COM 
29178718SMichael.Speer@Sun.COM 	ASSERT(type == MAC_RING_TYPE_RX);
29188718SMichael.Speer@Sun.COM 
29198718SMichael.Speer@Sun.COM 	switch (type) {
29208718SMichael.Speer@Sun.COM 	case MAC_RING_TYPE_RX:
29218718SMichael.Speer@Sun.COM 		group = &hxgep->rx_groups[groupid];
29228718SMichael.Speer@Sun.COM 		group->hxgep = hxgep;
29238718SMichael.Speer@Sun.COM 		group->ghandle = gh;
29248718SMichael.Speer@Sun.COM 		group->index = groupid;
29258718SMichael.Speer@Sun.COM 		group->type = type;
29268718SMichael.Speer@Sun.COM 
29278718SMichael.Speer@Sun.COM 		infop->mgi_driver = (mac_group_driver_t)group;
29288718SMichael.Speer@Sun.COM 		infop->mgi_start = hxge_rx_group_start;
29298718SMichael.Speer@Sun.COM 		infop->mgi_stop = hxge_rx_group_stop;
29308718SMichael.Speer@Sun.COM 		infop->mgi_addmac = hxge_rx_group_add_mac;
29318718SMichael.Speer@Sun.COM 		infop->mgi_remmac = hxge_rx_group_rem_mac;
29328718SMichael.Speer@Sun.COM 		infop->mgi_count = HXGE_MAX_RDCS;
29338718SMichael.Speer@Sun.COM 		break;
29348718SMichael.Speer@Sun.COM 
29358718SMichael.Speer@Sun.COM 	case MAC_RING_TYPE_TX:
29368718SMichael.Speer@Sun.COM 	default:
29378718SMichael.Speer@Sun.COM 		break;
29388718SMichael.Speer@Sun.COM 	}
29398718SMichael.Speer@Sun.COM }
29408718SMichael.Speer@Sun.COM 
2941*11878SVenu.Iyer@Sun.COM static int
hxge_ring_get_htable_idx(p_hxge_t hxgep,mac_ring_type_t type,uint32_t channel)2942*11878SVenu.Iyer@Sun.COM hxge_ring_get_htable_idx(p_hxge_t hxgep, mac_ring_type_t type, uint32_t channel)
2943*11878SVenu.Iyer@Sun.COM {
2944*11878SVenu.Iyer@Sun.COM 	int i;
2945*11878SVenu.Iyer@Sun.COM 
2946*11878SVenu.Iyer@Sun.COM 	ASSERT(hxgep->ldgvp != NULL);
2947*11878SVenu.Iyer@Sun.COM 
2948*11878SVenu.Iyer@Sun.COM 	switch (type) {
2949*11878SVenu.Iyer@Sun.COM 	case MAC_RING_TYPE_RX:
2950*11878SVenu.Iyer@Sun.COM 		for (i = 0; i < hxgep->ldgvp->maxldvs; i++) {
2951*11878SVenu.Iyer@Sun.COM 			if ((hxgep->ldgvp->ldvp[i].is_rxdma) &&
2952*11878SVenu.Iyer@Sun.COM 			    (hxgep->ldgvp->ldvp[i].channel == channel)) {
2953*11878SVenu.Iyer@Sun.COM 				return ((int)
2954*11878SVenu.Iyer@Sun.COM 				    hxgep->ldgvp->ldvp[i].ldgp->htable_idx);
2955*11878SVenu.Iyer@Sun.COM 			}
2956*11878SVenu.Iyer@Sun.COM 		}
2957*11878SVenu.Iyer@Sun.COM 		break;
2958*11878SVenu.Iyer@Sun.COM 
2959*11878SVenu.Iyer@Sun.COM 	case MAC_RING_TYPE_TX:
2960*11878SVenu.Iyer@Sun.COM 		for (i = 0; i < hxgep->ldgvp->maxldvs; i++) {
2961*11878SVenu.Iyer@Sun.COM 			if ((hxgep->ldgvp->ldvp[i].is_txdma) &&
2962*11878SVenu.Iyer@Sun.COM 			    (hxgep->ldgvp->ldvp[i].channel == channel)) {
2963*11878SVenu.Iyer@Sun.COM 				return ((int)
2964*11878SVenu.Iyer@Sun.COM 				    hxgep->ldgvp->ldvp[i].ldgp->htable_idx);
2965*11878SVenu.Iyer@Sun.COM 			}
2966*11878SVenu.Iyer@Sun.COM 		}
2967*11878SVenu.Iyer@Sun.COM 		break;
2968*11878SVenu.Iyer@Sun.COM 
2969*11878SVenu.Iyer@Sun.COM 	default:
2970*11878SVenu.Iyer@Sun.COM 		break;
2971*11878SVenu.Iyer@Sun.COM 	}
2972*11878SVenu.Iyer@Sun.COM 
2973*11878SVenu.Iyer@Sun.COM 	return (-1);
2974*11878SVenu.Iyer@Sun.COM }
2975*11878SVenu.Iyer@Sun.COM 
29768718SMichael.Speer@Sun.COM /*
29778718SMichael.Speer@Sun.COM  * Callback function for the GLDv3 layer to register all rings.
29788718SMichael.Speer@Sun.COM  */
29798718SMichael.Speer@Sun.COM /*ARGSUSED*/
29808718SMichael.Speer@Sun.COM static void
hxge_fill_ring(void * arg,mac_ring_type_t type,const int rg_index,const int index,mac_ring_info_t * infop,mac_ring_handle_t rh)29818718SMichael.Speer@Sun.COM hxge_fill_ring(void *arg, mac_ring_type_t type, const int rg_index,
29828718SMichael.Speer@Sun.COM     const int index, mac_ring_info_t *infop, mac_ring_handle_t rh)
29838718SMichael.Speer@Sun.COM {
29848718SMichael.Speer@Sun.COM 	p_hxge_t	hxgep = arg;
29858718SMichael.Speer@Sun.COM 
2986*11878SVenu.Iyer@Sun.COM 	ASSERT(hxgep != NULL);
2987*11878SVenu.Iyer@Sun.COM 	ASSERT(infop != NULL);
2988*11878SVenu.Iyer@Sun.COM 
29898718SMichael.Speer@Sun.COM 	switch (type) {
29908718SMichael.Speer@Sun.COM 	case MAC_RING_TYPE_TX: {
29918718SMichael.Speer@Sun.COM 		p_hxge_ring_handle_t	rhp;
2992*11878SVenu.Iyer@Sun.COM 		mac_intr_t		*mintr = &infop->mri_intr;
2993*11878SVenu.Iyer@Sun.COM 		p_hxge_intr_t		intrp;
2994*11878SVenu.Iyer@Sun.COM 		int			htable_idx;
29958718SMichael.Speer@Sun.COM 
29968718SMichael.Speer@Sun.COM 		ASSERT((index >= 0) && (index < HXGE_MAX_TDCS));
29978718SMichael.Speer@Sun.COM 		rhp = &hxgep->tx_ring_handles[index];
29988718SMichael.Speer@Sun.COM 		rhp->hxgep = hxgep;
29998718SMichael.Speer@Sun.COM 		rhp->index = index;
30008718SMichael.Speer@Sun.COM 		rhp->ring_handle = rh;
30018718SMichael.Speer@Sun.COM 		infop->mri_driver = (mac_ring_driver_t)rhp;
30028718SMichael.Speer@Sun.COM 		infop->mri_start = hxge_tx_ring_start;
30038718SMichael.Speer@Sun.COM 		infop->mri_stop = hxge_tx_ring_stop;
30048718SMichael.Speer@Sun.COM 		infop->mri_tx = hxge_tx_ring_send;
3005*11878SVenu.Iyer@Sun.COM 		infop->mri_stat = hxge_tx_ring_stat;
3006*11878SVenu.Iyer@Sun.COM 
3007*11878SVenu.Iyer@Sun.COM 		intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3008*11878SVenu.Iyer@Sun.COM 		htable_idx = hxge_ring_get_htable_idx(hxgep, type, index);
3009*11878SVenu.Iyer@Sun.COM 		if (htable_idx >= 0)
3010*11878SVenu.Iyer@Sun.COM 			mintr->mi_ddi_handle = intrp->htable[htable_idx];
3011*11878SVenu.Iyer@Sun.COM 		else
3012*11878SVenu.Iyer@Sun.COM 			mintr->mi_ddi_handle = NULL;
30138718SMichael.Speer@Sun.COM 		break;
30148718SMichael.Speer@Sun.COM 	}
3015*11878SVenu.Iyer@Sun.COM 
30168718SMichael.Speer@Sun.COM 	case MAC_RING_TYPE_RX: {
30178718SMichael.Speer@Sun.COM 		p_hxge_ring_handle_t    rhp;
30188718SMichael.Speer@Sun.COM 		mac_intr_t		hxge_mac_intr;
3019*11878SVenu.Iyer@Sun.COM 		p_hxge_intr_t		intrp;
3020*11878SVenu.Iyer@Sun.COM 		int			htable_idx;
30218718SMichael.Speer@Sun.COM 
30228718SMichael.Speer@Sun.COM 		ASSERT((index >= 0) && (index < HXGE_MAX_RDCS));
30238718SMichael.Speer@Sun.COM 		rhp = &hxgep->rx_ring_handles[index];
30248718SMichael.Speer@Sun.COM 		rhp->hxgep = hxgep;
30258718SMichael.Speer@Sun.COM 		rhp->index = index;
30268718SMichael.Speer@Sun.COM 		rhp->ring_handle = rh;
30278718SMichael.Speer@Sun.COM 
30288718SMichael.Speer@Sun.COM 		/*
30298718SMichael.Speer@Sun.COM 		 * Entrypoint to enable interrupt (disable poll) and
30308718SMichael.Speer@Sun.COM 		 * disable interrupt (enable poll).
30318718SMichael.Speer@Sun.COM 		 */
30328718SMichael.Speer@Sun.COM 		hxge_mac_intr.mi_handle = (mac_intr_handle_t)rhp;
3033*11878SVenu.Iyer@Sun.COM 		hxge_mac_intr.mi_enable = (mac_intr_enable_t)hxge_disable_poll;
3034*11878SVenu.Iyer@Sun.COM 		hxge_mac_intr.mi_disable = (mac_intr_disable_t)hxge_enable_poll;
3035*11878SVenu.Iyer@Sun.COM 
3036*11878SVenu.Iyer@Sun.COM 		intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3037*11878SVenu.Iyer@Sun.COM 		htable_idx = hxge_ring_get_htable_idx(hxgep, type, index);
3038*11878SVenu.Iyer@Sun.COM 		if (htable_idx >= 0)
3039*11878SVenu.Iyer@Sun.COM 			hxge_mac_intr.mi_ddi_handle = intrp->htable[htable_idx];
3040*11878SVenu.Iyer@Sun.COM 		else
3041*11878SVenu.Iyer@Sun.COM 			hxge_mac_intr.mi_ddi_handle = NULL;
3042*11878SVenu.Iyer@Sun.COM 
30438718SMichael.Speer@Sun.COM 		infop->mri_driver = (mac_ring_driver_t)rhp;
30448718SMichael.Speer@Sun.COM 		infop->mri_start = hxge_rx_ring_start;
30458718SMichael.Speer@Sun.COM 		infop->mri_stop = hxge_rx_ring_stop;
30468718SMichael.Speer@Sun.COM 		infop->mri_intr = hxge_mac_intr;
30478718SMichael.Speer@Sun.COM 		infop->mri_poll = hxge_rx_poll;
3048*11878SVenu.Iyer@Sun.COM 		infop->mri_stat = hxge_rx_ring_stat;
30498718SMichael.Speer@Sun.COM 		break;
30508718SMichael.Speer@Sun.COM 	}
3051*11878SVenu.Iyer@Sun.COM 
30528718SMichael.Speer@Sun.COM 	default:
30538718SMichael.Speer@Sun.COM 		break;
30548718SMichael.Speer@Sun.COM 	}
30558718SMichael.Speer@Sun.COM }
30568718SMichael.Speer@Sun.COM 
30578718SMichael.Speer@Sun.COM /*ARGSUSED*/
30586349Sqs148142 boolean_t
hxge_m_getcapab(void * arg,mac_capab_t cap,void * cap_data)30596349Sqs148142 hxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
30606349Sqs148142 {
30618718SMichael.Speer@Sun.COM 	p_hxge_t	hxgep = arg;
30626349Sqs148142 
30636349Sqs148142 	switch (cap) {
30648718SMichael.Speer@Sun.COM 	case MAC_CAPAB_HCKSUM: {
30658718SMichael.Speer@Sun.COM 		uint32_t	*txflags = cap_data;
30668718SMichael.Speer@Sun.COM 
30676349Sqs148142 		*txflags = HCKSUM_INET_PARTIAL;
30686349Sqs148142 		break;
30698718SMichael.Speer@Sun.COM 	}
30708718SMichael.Speer@Sun.COM 
30718718SMichael.Speer@Sun.COM 	case MAC_CAPAB_RINGS: {
30728718SMichael.Speer@Sun.COM 		mac_capab_rings_t	*cap_rings = cap_data;
30738718SMichael.Speer@Sun.COM 
30748718SMichael.Speer@Sun.COM 		MUTEX_ENTER(hxgep->genlock);
30758718SMichael.Speer@Sun.COM 		if (cap_rings->mr_type == MAC_RING_TYPE_RX) {
30768718SMichael.Speer@Sun.COM 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
30778718SMichael.Speer@Sun.COM 			cap_rings->mr_rnum = HXGE_MAX_RDCS;
30788718SMichael.Speer@Sun.COM 			cap_rings->mr_rget = hxge_fill_ring;
30798718SMichael.Speer@Sun.COM 			cap_rings->mr_gnum = HXGE_MAX_RX_GROUPS;
30808718SMichael.Speer@Sun.COM 			cap_rings->mr_gget = hxge_group_get;
30818718SMichael.Speer@Sun.COM 			cap_rings->mr_gaddring = NULL;
30828718SMichael.Speer@Sun.COM 			cap_rings->mr_gremring = NULL;
30838718SMichael.Speer@Sun.COM 		} else {
30848718SMichael.Speer@Sun.COM 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
30858718SMichael.Speer@Sun.COM 			cap_rings->mr_rnum = HXGE_MAX_TDCS;
30868718SMichael.Speer@Sun.COM 			cap_rings->mr_rget = hxge_fill_ring;
30878718SMichael.Speer@Sun.COM 			cap_rings->mr_gnum = 0;
30888718SMichael.Speer@Sun.COM 			cap_rings->mr_gget = NULL;
30898718SMichael.Speer@Sun.COM 			cap_rings->mr_gaddring = NULL;
30908718SMichael.Speer@Sun.COM 			cap_rings->mr_gremring = NULL;
30918718SMichael.Speer@Sun.COM 		}
30928718SMichael.Speer@Sun.COM 		MUTEX_EXIT(hxgep->genlock);
30938718SMichael.Speer@Sun.COM 		break;
30948718SMichael.Speer@Sun.COM 	}
30956349Sqs148142 
30966349Sqs148142 	default:
30976349Sqs148142 		return (B_FALSE);
30986349Sqs148142 	}
30996349Sqs148142 	return (B_TRUE);
31006349Sqs148142 }
31016349Sqs148142 
31027584SQiyan.Sun@Sun.COM static boolean_t
hxge_param_locked(mac_prop_id_t pr_num)31037584SQiyan.Sun@Sun.COM hxge_param_locked(mac_prop_id_t pr_num)
31047584SQiyan.Sun@Sun.COM {
31057584SQiyan.Sun@Sun.COM 	/*
31067584SQiyan.Sun@Sun.COM 	 * All adv_* parameters are locked (read-only) while
31077584SQiyan.Sun@Sun.COM 	 * the device is in any sort of loopback mode ...
31087584SQiyan.Sun@Sun.COM 	 */
31097584SQiyan.Sun@Sun.COM 	switch (pr_num) {
31107584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_1000FDX_CAP:
31117584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_1000FDX_CAP:
31127584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_1000HDX_CAP:
31137584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_1000HDX_CAP:
31147584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_100FDX_CAP:
31157584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_100FDX_CAP:
31167584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_100HDX_CAP:
31177584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_100HDX_CAP:
31187584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_10FDX_CAP:
31197584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_10FDX_CAP:
31207584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_10HDX_CAP:
31217584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_10HDX_CAP:
31227584SQiyan.Sun@Sun.COM 		case MAC_PROP_AUTONEG:
31237584SQiyan.Sun@Sun.COM 		case MAC_PROP_FLOWCTRL:
31247584SQiyan.Sun@Sun.COM 			return (B_TRUE);
31257584SQiyan.Sun@Sun.COM 	}
31267584SQiyan.Sun@Sun.COM 	return (B_FALSE);
31277584SQiyan.Sun@Sun.COM }
31287584SQiyan.Sun@Sun.COM 
31297584SQiyan.Sun@Sun.COM /*
31307584SQiyan.Sun@Sun.COM  * callback functions for set/get of properties
31317584SQiyan.Sun@Sun.COM  */
31327584SQiyan.Sun@Sun.COM static int
hxge_m_setprop(void * barg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,const void * pr_val)31337584SQiyan.Sun@Sun.COM hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
31347584SQiyan.Sun@Sun.COM     uint_t pr_valsize, const void *pr_val)
31357584SQiyan.Sun@Sun.COM {
31367584SQiyan.Sun@Sun.COM 	hxge_t		*hxgep = barg;
31377584SQiyan.Sun@Sun.COM 	p_hxge_stats_t	statsp;
31387584SQiyan.Sun@Sun.COM 	int		err = 0;
31397584SQiyan.Sun@Sun.COM 	uint32_t	new_mtu, old_framesize, new_framesize;
31407584SQiyan.Sun@Sun.COM 
31417584SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "==> hxge_m_setprop"));
31427584SQiyan.Sun@Sun.COM 
31437584SQiyan.Sun@Sun.COM 	statsp = hxgep->statsp;
31448718SMichael.Speer@Sun.COM 	MUTEX_ENTER(hxgep->genlock);
31457584SQiyan.Sun@Sun.COM 	if (statsp->port_stats.lb_mode != hxge_lb_normal &&
31467584SQiyan.Sun@Sun.COM 	    hxge_param_locked(pr_num)) {
31477584SQiyan.Sun@Sun.COM 		/*
31487584SQiyan.Sun@Sun.COM 		 * All adv_* parameters are locked (read-only)
31497584SQiyan.Sun@Sun.COM 		 * while the device is in any sort of loopback mode.
31507584SQiyan.Sun@Sun.COM 		 */
31517584SQiyan.Sun@Sun.COM 		HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
31527584SQiyan.Sun@Sun.COM 		    "==> hxge_m_setprop: loopback mode: read only"));
31538718SMichael.Speer@Sun.COM 		MUTEX_EXIT(hxgep->genlock);
31547584SQiyan.Sun@Sun.COM 		return (EBUSY);
31557584SQiyan.Sun@Sun.COM 	}
31567584SQiyan.Sun@Sun.COM 
31577584SQiyan.Sun@Sun.COM 	switch (pr_num) {
31587584SQiyan.Sun@Sun.COM 		/*
31597584SQiyan.Sun@Sun.COM 		 * These properties are either not exist or read only
31607584SQiyan.Sun@Sun.COM 		 */
31617584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_1000FDX_CAP:
31627584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_100FDX_CAP:
31637584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_10FDX_CAP:
31647584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_1000HDX_CAP:
31657584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_100HDX_CAP:
31667584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_10HDX_CAP:
31677584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_1000FDX_CAP:
31687584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_1000HDX_CAP:
31697584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_100FDX_CAP:
31707584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_100HDX_CAP:
31717584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_10FDX_CAP:
31727584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_10HDX_CAP:
31737584SQiyan.Sun@Sun.COM 		case MAC_PROP_STATUS:
31747584SQiyan.Sun@Sun.COM 		case MAC_PROP_SPEED:
31757584SQiyan.Sun@Sun.COM 		case MAC_PROP_DUPLEX:
31767584SQiyan.Sun@Sun.COM 		case MAC_PROP_AUTONEG:
31777584SQiyan.Sun@Sun.COM 		/*
31787584SQiyan.Sun@Sun.COM 		 * Flow control is handled in the shared domain and
31797584SQiyan.Sun@Sun.COM 		 * it is readonly here.
31807584SQiyan.Sun@Sun.COM 		 */
31817584SQiyan.Sun@Sun.COM 		case MAC_PROP_FLOWCTRL:
31827584SQiyan.Sun@Sun.COM 			err = EINVAL;
31837584SQiyan.Sun@Sun.COM 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
31847584SQiyan.Sun@Sun.COM 			    "==> hxge_m_setprop:  read only property %d",
31857584SQiyan.Sun@Sun.COM 			    pr_num));
31867584SQiyan.Sun@Sun.COM 			break;
31877584SQiyan.Sun@Sun.COM 
31887584SQiyan.Sun@Sun.COM 		case MAC_PROP_MTU:
31897584SQiyan.Sun@Sun.COM 			bcopy(pr_val, &new_mtu, sizeof (new_mtu));
31907584SQiyan.Sun@Sun.COM 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
31917584SQiyan.Sun@Sun.COM 			    "==> hxge_m_setprop: set MTU: %d", new_mtu));
31927584SQiyan.Sun@Sun.COM 
31937584SQiyan.Sun@Sun.COM 			new_framesize = new_mtu + MTU_TO_FRAME_SIZE;
31947584SQiyan.Sun@Sun.COM 			if (new_framesize == hxgep->vmac.maxframesize) {
31957584SQiyan.Sun@Sun.COM 				err = 0;
31967584SQiyan.Sun@Sun.COM 				break;
31977584SQiyan.Sun@Sun.COM 			}
31987584SQiyan.Sun@Sun.COM 
31998118SVasumathi.Sundaram@Sun.COM 			if (hxgep->hxge_mac_state == HXGE_MAC_STARTED) {
32008118SVasumathi.Sundaram@Sun.COM 				err = EBUSY;
32018118SVasumathi.Sundaram@Sun.COM 				break;
32028118SVasumathi.Sundaram@Sun.COM 			}
32038118SVasumathi.Sundaram@Sun.COM 
32047584SQiyan.Sun@Sun.COM 			if (new_framesize < MIN_FRAME_SIZE ||
32057584SQiyan.Sun@Sun.COM 			    new_framesize > MAX_FRAME_SIZE) {
32067584SQiyan.Sun@Sun.COM 				err = EINVAL;
32077584SQiyan.Sun@Sun.COM 				break;
32087584SQiyan.Sun@Sun.COM 			}
32097584SQiyan.Sun@Sun.COM 
32107584SQiyan.Sun@Sun.COM 			old_framesize = hxgep->vmac.maxframesize;
32117584SQiyan.Sun@Sun.COM 			hxgep->vmac.maxframesize = (uint16_t)new_framesize;
32127584SQiyan.Sun@Sun.COM 
32137584SQiyan.Sun@Sun.COM 			if (hxge_vmac_set_framesize(hxgep)) {
32147584SQiyan.Sun@Sun.COM 				hxgep->vmac.maxframesize =
32157584SQiyan.Sun@Sun.COM 				    (uint16_t)old_framesize;
32167584SQiyan.Sun@Sun.COM 				err = EINVAL;
32177584SQiyan.Sun@Sun.COM 				break;
32187584SQiyan.Sun@Sun.COM 			}
32197584SQiyan.Sun@Sun.COM 
32207584SQiyan.Sun@Sun.COM 			err = mac_maxsdu_update(hxgep->mach, new_mtu);
32217584SQiyan.Sun@Sun.COM 			if (err) {
32227584SQiyan.Sun@Sun.COM 				hxgep->vmac.maxframesize =
32237584SQiyan.Sun@Sun.COM 				    (uint16_t)old_framesize;
32247584SQiyan.Sun@Sun.COM 				(void) hxge_vmac_set_framesize(hxgep);
32257584SQiyan.Sun@Sun.COM 			}
32267584SQiyan.Sun@Sun.COM 
32277584SQiyan.Sun@Sun.COM 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
32287584SQiyan.Sun@Sun.COM 			    "==> hxge_m_setprop: set MTU: %d maxframe %d",
32297584SQiyan.Sun@Sun.COM 			    new_mtu, hxgep->vmac.maxframesize));
32307584SQiyan.Sun@Sun.COM 			break;
32317584SQiyan.Sun@Sun.COM 
32327584SQiyan.Sun@Sun.COM 		case MAC_PROP_PRIVATE:
32337584SQiyan.Sun@Sun.COM 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
32347584SQiyan.Sun@Sun.COM 			    "==> hxge_m_setprop: private property"));
32357584SQiyan.Sun@Sun.COM 			err = hxge_set_priv_prop(hxgep, pr_name, pr_valsize,
32367584SQiyan.Sun@Sun.COM 			    pr_val);
32377584SQiyan.Sun@Sun.COM 			break;
32387584SQiyan.Sun@Sun.COM 
32397584SQiyan.Sun@Sun.COM 		default:
32407584SQiyan.Sun@Sun.COM 			err = ENOTSUP;
32417584SQiyan.Sun@Sun.COM 			break;
32427584SQiyan.Sun@Sun.COM 	}
32437584SQiyan.Sun@Sun.COM 
32448718SMichael.Speer@Sun.COM 	MUTEX_EXIT(hxgep->genlock);
32457584SQiyan.Sun@Sun.COM 
32467584SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
32477584SQiyan.Sun@Sun.COM 	    "<== hxge_m_setprop (return %d)", err));
32487584SQiyan.Sun@Sun.COM 
32497584SQiyan.Sun@Sun.COM 	return (err);
32507584SQiyan.Sun@Sun.COM }
32517584SQiyan.Sun@Sun.COM 
32527584SQiyan.Sun@Sun.COM static int
hxge_m_getprop(void * barg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,void * pr_val)32537584SQiyan.Sun@Sun.COM hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
3254*11878SVenu.Iyer@Sun.COM     uint_t pr_valsize, void *pr_val)
32557584SQiyan.Sun@Sun.COM {
32567584SQiyan.Sun@Sun.COM 	hxge_t 		*hxgep = barg;
32577584SQiyan.Sun@Sun.COM 	p_hxge_stats_t	statsp = hxgep->statsp;
32587584SQiyan.Sun@Sun.COM 	int		err = 0;
32597584SQiyan.Sun@Sun.COM 	link_flowctrl_t fl;
32607584SQiyan.Sun@Sun.COM 	uint64_t	tmp = 0;
32617584SQiyan.Sun@Sun.COM 	link_state_t	ls;
32627584SQiyan.Sun@Sun.COM 
32637584SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
32647584SQiyan.Sun@Sun.COM 	    "==> hxge_m_getprop: pr_num %d", pr_num));
32657584SQiyan.Sun@Sun.COM 
32667584SQiyan.Sun@Sun.COM 	switch (pr_num) {
32677584SQiyan.Sun@Sun.COM 		case MAC_PROP_DUPLEX:
32687584SQiyan.Sun@Sun.COM 			*(uint8_t *)pr_val = statsp->mac_stats.link_duplex;
32697584SQiyan.Sun@Sun.COM 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
32707584SQiyan.Sun@Sun.COM 			    "==> hxge_m_getprop: duplex mode %d",
32717584SQiyan.Sun@Sun.COM 			    *(uint8_t *)pr_val));
32727584SQiyan.Sun@Sun.COM 			break;
32737584SQiyan.Sun@Sun.COM 
32747584SQiyan.Sun@Sun.COM 		case MAC_PROP_SPEED:
3275*11878SVenu.Iyer@Sun.COM 			ASSERT(pr_valsize >= sizeof (uint64_t));
32767584SQiyan.Sun@Sun.COM 			tmp = statsp->mac_stats.link_speed * 1000000ull;
32777584SQiyan.Sun@Sun.COM 			bcopy(&tmp, pr_val, sizeof (tmp));
32787584SQiyan.Sun@Sun.COM 			break;
32797584SQiyan.Sun@Sun.COM 
32807584SQiyan.Sun@Sun.COM 		case MAC_PROP_STATUS:
3281*11878SVenu.Iyer@Sun.COM 			ASSERT(pr_valsize >= sizeof (link_state_t));
32827584SQiyan.Sun@Sun.COM 			if (!statsp->mac_stats.link_up)
32837584SQiyan.Sun@Sun.COM 				ls = LINK_STATE_DOWN;
32847584SQiyan.Sun@Sun.COM 			else
32857584SQiyan.Sun@Sun.COM 				ls = LINK_STATE_UP;
32867584SQiyan.Sun@Sun.COM 			bcopy(&ls, pr_val, sizeof (ls));
32877584SQiyan.Sun@Sun.COM 			break;
32887584SQiyan.Sun@Sun.COM 
32897584SQiyan.Sun@Sun.COM 		case MAC_PROP_FLOWCTRL:
32907584SQiyan.Sun@Sun.COM 			/*
32917584SQiyan.Sun@Sun.COM 			 * Flow control is supported by the shared domain and
32927584SQiyan.Sun@Sun.COM 			 * it is currently transmit only
32937584SQiyan.Sun@Sun.COM 			 */
3294*11878SVenu.Iyer@Sun.COM 			ASSERT(pr_valsize < sizeof (link_flowctrl_t));
32957584SQiyan.Sun@Sun.COM 			fl = LINK_FLOWCTRL_TX;
32967584SQiyan.Sun@Sun.COM 			bcopy(&fl, pr_val, sizeof (fl));
32977584SQiyan.Sun@Sun.COM 			break;
32987584SQiyan.Sun@Sun.COM 		case MAC_PROP_AUTONEG:
32997584SQiyan.Sun@Sun.COM 			/* 10G link only and it is not negotiable */
33007584SQiyan.Sun@Sun.COM 			*(uint8_t *)pr_val = 0;
33017584SQiyan.Sun@Sun.COM 			break;
33027584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_1000FDX_CAP:
33037584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_100FDX_CAP:
33047584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_10FDX_CAP:
33057584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_1000HDX_CAP:
33067584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_100HDX_CAP:
33077584SQiyan.Sun@Sun.COM 		case MAC_PROP_ADV_10HDX_CAP:
33087584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_1000FDX_CAP:
33097584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_100FDX_CAP:
33107584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_10FDX_CAP:
33117584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_1000HDX_CAP:
33127584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_100HDX_CAP:
33137584SQiyan.Sun@Sun.COM 		case MAC_PROP_EN_10HDX_CAP:
33147584SQiyan.Sun@Sun.COM 			err = ENOTSUP;
33157584SQiyan.Sun@Sun.COM 			break;
33167584SQiyan.Sun@Sun.COM 
33177584SQiyan.Sun@Sun.COM 		case MAC_PROP_PRIVATE:
3318*11878SVenu.Iyer@Sun.COM 			err = hxge_get_priv_prop(hxgep, pr_name, pr_valsize,
3319*11878SVenu.Iyer@Sun.COM 			    pr_val);
33207584SQiyan.Sun@Sun.COM 			break;
3321*11878SVenu.Iyer@Sun.COM 
33227584SQiyan.Sun@Sun.COM 		default:
33237584SQiyan.Sun@Sun.COM 			err = EINVAL;
33247584SQiyan.Sun@Sun.COM 			break;
33257584SQiyan.Sun@Sun.COM 	}
33267584SQiyan.Sun@Sun.COM 
33277584SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "<== hxge_m_getprop"));
33287584SQiyan.Sun@Sun.COM 
33297584SQiyan.Sun@Sun.COM 	return (err);
33307584SQiyan.Sun@Sun.COM }
33317584SQiyan.Sun@Sun.COM 
3332*11878SVenu.Iyer@Sun.COM static void
hxge_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)3333*11878SVenu.Iyer@Sun.COM hxge_m_propinfo(void *arg, const char *pr_name,
3334*11878SVenu.Iyer@Sun.COM     mac_prop_id_t pr_num, mac_prop_info_handle_t prh)
3335*11878SVenu.Iyer@Sun.COM {
3336*11878SVenu.Iyer@Sun.COM 	_NOTE(ARGUNUSED(arg));
3337*11878SVenu.Iyer@Sun.COM 	switch (pr_num) {
3338*11878SVenu.Iyer@Sun.COM 	case MAC_PROP_DUPLEX:
3339*11878SVenu.Iyer@Sun.COM 	case MAC_PROP_SPEED:
3340*11878SVenu.Iyer@Sun.COM 	case MAC_PROP_STATUS:
3341*11878SVenu.Iyer@Sun.COM 	case MAC_PROP_AUTONEG:
3342*11878SVenu.Iyer@Sun.COM 	case MAC_PROP_FLOWCTRL:
3343*11878SVenu.Iyer@Sun.COM 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
3344*11878SVenu.Iyer@Sun.COM 		break;
3345*11878SVenu.Iyer@Sun.COM 
3346*11878SVenu.Iyer@Sun.COM 	case MAC_PROP_MTU:
3347*11878SVenu.Iyer@Sun.COM 		mac_prop_info_set_range_uint32(prh,
3348*11878SVenu.Iyer@Sun.COM 		    MIN_FRAME_SIZE - MTU_TO_FRAME_SIZE,
3349*11878SVenu.Iyer@Sun.COM 		    MAX_FRAME_SIZE - MTU_TO_FRAME_SIZE);
3350*11878SVenu.Iyer@Sun.COM 		break;
3351*11878SVenu.Iyer@Sun.COM 
3352*11878SVenu.Iyer@Sun.COM 	case MAC_PROP_PRIVATE: {
3353*11878SVenu.Iyer@Sun.COM 		char valstr[MAXNAMELEN];
3354*11878SVenu.Iyer@Sun.COM 
3355*11878SVenu.Iyer@Sun.COM 		bzero(valstr, sizeof (valstr));
3356*11878SVenu.Iyer@Sun.COM 
3357*11878SVenu.Iyer@Sun.COM 		/* Receive Interrupt Blanking Parameters */
3358*11878SVenu.Iyer@Sun.COM 		if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
3359*11878SVenu.Iyer@Sun.COM 			(void) snprintf(valstr, sizeof (valstr), "%d",
3360*11878SVenu.Iyer@Sun.COM 			    RXDMA_RCR_TO_DEFAULT);
3361*11878SVenu.Iyer@Sun.COM 		} else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
3362*11878SVenu.Iyer@Sun.COM 			(void) snprintf(valstr, sizeof (valstr), "%d",
3363*11878SVenu.Iyer@Sun.COM 			    RXDMA_RCR_PTHRES_DEFAULT);
3364*11878SVenu.Iyer@Sun.COM 
3365*11878SVenu.Iyer@Sun.COM 		/* Classification and Load Distribution Configuration */
3366*11878SVenu.Iyer@Sun.COM 		} else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 ||
3367*11878SVenu.Iyer@Sun.COM 		    strcmp(pr_name, "_class_opt_ipv4_udp") == 0 ||
3368*11878SVenu.Iyer@Sun.COM 		    strcmp(pr_name, "_class_opt_ipv4_ah") == 0 ||
3369*11878SVenu.Iyer@Sun.COM 		    strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 ||
3370*11878SVenu.Iyer@Sun.COM 		    strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 ||
3371*11878SVenu.Iyer@Sun.COM 		    strcmp(pr_name, "_class_opt_ipv6_udp") == 0 ||
3372*11878SVenu.Iyer@Sun.COM 		    strcmp(pr_name, "_class_opt_ipv6_ah") == 0 ||
3373*11878SVenu.Iyer@Sun.COM 		    strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
3374*11878SVenu.Iyer@Sun.COM 			(void) snprintf(valstr, sizeof (valstr), "%d",
3375*11878SVenu.Iyer@Sun.COM 			    HXGE_CLASS_TCAM_LOOKUP);
3376*11878SVenu.Iyer@Sun.COM 		}
3377*11878SVenu.Iyer@Sun.COM 
3378*11878SVenu.Iyer@Sun.COM 		if (strlen(valstr) > 0)
3379*11878SVenu.Iyer@Sun.COM 			mac_prop_info_set_default_str(prh, valstr);
3380*11878SVenu.Iyer@Sun.COM 		break;
3381*11878SVenu.Iyer@Sun.COM 	}
3382*11878SVenu.Iyer@Sun.COM 	}
3383*11878SVenu.Iyer@Sun.COM }
3384*11878SVenu.Iyer@Sun.COM 
3385*11878SVenu.Iyer@Sun.COM 
33867584SQiyan.Sun@Sun.COM /* ARGSUSED */
33877584SQiyan.Sun@Sun.COM static int
hxge_set_priv_prop(p_hxge_t hxgep,const char * pr_name,uint_t pr_valsize,const void * pr_val)33887584SQiyan.Sun@Sun.COM hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize,
33897584SQiyan.Sun@Sun.COM     const void *pr_val)
33907584SQiyan.Sun@Sun.COM {
33917584SQiyan.Sun@Sun.COM 	p_hxge_param_t	param_arr = hxgep->param_arr;
33927584SQiyan.Sun@Sun.COM 	int		err = 0;
33937584SQiyan.Sun@Sun.COM 
33947584SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
33957584SQiyan.Sun@Sun.COM 	    "==> hxge_set_priv_prop: name %s (value %s)", pr_name, pr_val));
33967584SQiyan.Sun@Sun.COM 
33977584SQiyan.Sun@Sun.COM 	if (pr_val == NULL) {
33987584SQiyan.Sun@Sun.COM 		return (EINVAL);
33997584SQiyan.Sun@Sun.COM 	}
34007584SQiyan.Sun@Sun.COM 
34017584SQiyan.Sun@Sun.COM 	/* Blanking */
34027584SQiyan.Sun@Sun.COM 	if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
34037584SQiyan.Sun@Sun.COM 		err = hxge_param_rx_intr_time(hxgep, NULL, NULL,
34047584SQiyan.Sun@Sun.COM 		    (char *)pr_val, (caddr_t)&param_arr[param_rxdma_intr_time]);
34057584SQiyan.Sun@Sun.COM 	} else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
34067584SQiyan.Sun@Sun.COM 		err = hxge_param_rx_intr_pkts(hxgep, NULL, NULL,
34077584SQiyan.Sun@Sun.COM 		    (char *)pr_val, (caddr_t)&param_arr[param_rxdma_intr_pkts]);
34087584SQiyan.Sun@Sun.COM 
34097584SQiyan.Sun@Sun.COM 	/* Classification */
34107584SQiyan.Sun@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
34117584SQiyan.Sun@Sun.COM 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34127584SQiyan.Sun@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv4_tcp]);
34137584SQiyan.Sun@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
34147584SQiyan.Sun@Sun.COM 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34157584SQiyan.Sun@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv4_udp]);
34167584SQiyan.Sun@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
34177584SQiyan.Sun@Sun.COM 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34187584SQiyan.Sun@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv4_ah]);
34197584SQiyan.Sun@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
34207584SQiyan.Sun@Sun.COM 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34217584SQiyan.Sun@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv4_sctp]);
34227584SQiyan.Sun@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
34237584SQiyan.Sun@Sun.COM 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34247584SQiyan.Sun@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv6_tcp]);
34257584SQiyan.Sun@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
34267584SQiyan.Sun@Sun.COM 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34277584SQiyan.Sun@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv6_udp]);
34287584SQiyan.Sun@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
34297584SQiyan.Sun@Sun.COM 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34307584SQiyan.Sun@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv6_ah]);
34317584SQiyan.Sun@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
34327584SQiyan.Sun@Sun.COM 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
34337584SQiyan.Sun@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv6_sctp]);
34347584SQiyan.Sun@Sun.COM 	} else {
34357584SQiyan.Sun@Sun.COM 		err = EINVAL;
34367584SQiyan.Sun@Sun.COM 	}
34377584SQiyan.Sun@Sun.COM 
34387584SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
34397584SQiyan.Sun@Sun.COM 	    "<== hxge_set_priv_prop: err %d", err));
34407584SQiyan.Sun@Sun.COM 
34417584SQiyan.Sun@Sun.COM 	return (err);
34427584SQiyan.Sun@Sun.COM }
34437584SQiyan.Sun@Sun.COM 
34447584SQiyan.Sun@Sun.COM static int
hxge_get_priv_prop(p_hxge_t hxgep,const char * pr_name,uint_t pr_valsize,void * pr_val)3445*11878SVenu.Iyer@Sun.COM hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize,
3446*11878SVenu.Iyer@Sun.COM     void *pr_val)
34477584SQiyan.Sun@Sun.COM {
34487584SQiyan.Sun@Sun.COM 	p_hxge_param_t	param_arr = hxgep->param_arr;
34497584SQiyan.Sun@Sun.COM 	char		valstr[MAXNAMELEN];
34507584SQiyan.Sun@Sun.COM 	int		err = 0;
34517584SQiyan.Sun@Sun.COM 	uint_t		strsize;
34527584SQiyan.Sun@Sun.COM 	int		value = 0;
34537584SQiyan.Sun@Sun.COM 
34547584SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
34557584SQiyan.Sun@Sun.COM 	    "==> hxge_get_priv_prop: property %s", pr_name));
34567584SQiyan.Sun@Sun.COM 
3457*11878SVenu.Iyer@Sun.COM 	/* Receive Interrupt Blanking Parameters */
3458*11878SVenu.Iyer@Sun.COM 	if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
3459*11878SVenu.Iyer@Sun.COM 		value = hxgep->intr_timeout;
3460*11878SVenu.Iyer@Sun.COM 	} else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
3461*11878SVenu.Iyer@Sun.COM 		value = hxgep->intr_threshold;
3462*11878SVenu.Iyer@Sun.COM 
3463*11878SVenu.Iyer@Sun.COM 	/* Classification and Load Distribution Configuration */
3464*11878SVenu.Iyer@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
3465*11878SVenu.Iyer@Sun.COM 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3466*11878SVenu.Iyer@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv4_tcp]);
3467*11878SVenu.Iyer@Sun.COM 
3468*11878SVenu.Iyer@Sun.COM 		value = (int)param_arr[param_class_opt_ipv4_tcp].value;
3469*11878SVenu.Iyer@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
3470*11878SVenu.Iyer@Sun.COM 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3471*11878SVenu.Iyer@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv4_udp]);
3472*11878SVenu.Iyer@Sun.COM 
3473*11878SVenu.Iyer@Sun.COM 		value = (int)param_arr[param_class_opt_ipv4_udp].value;
3474*11878SVenu.Iyer@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
3475*11878SVenu.Iyer@Sun.COM 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3476*11878SVenu.Iyer@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv4_ah]);
3477*11878SVenu.Iyer@Sun.COM 
3478*11878SVenu.Iyer@Sun.COM 		value = (int)param_arr[param_class_opt_ipv4_ah].value;
3479*11878SVenu.Iyer@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
3480*11878SVenu.Iyer@Sun.COM 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3481*11878SVenu.Iyer@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv4_sctp]);
3482*11878SVenu.Iyer@Sun.COM 
3483*11878SVenu.Iyer@Sun.COM 		value = (int)param_arr[param_class_opt_ipv4_sctp].value;
3484*11878SVenu.Iyer@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
3485*11878SVenu.Iyer@Sun.COM 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3486*11878SVenu.Iyer@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv6_tcp]);
3487*11878SVenu.Iyer@Sun.COM 
3488*11878SVenu.Iyer@Sun.COM 		value = (int)param_arr[param_class_opt_ipv6_tcp].value;
3489*11878SVenu.Iyer@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
3490*11878SVenu.Iyer@Sun.COM 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3491*11878SVenu.Iyer@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv6_udp]);
3492*11878SVenu.Iyer@Sun.COM 
3493*11878SVenu.Iyer@Sun.COM 		value = (int)param_arr[param_class_opt_ipv6_udp].value;
3494*11878SVenu.Iyer@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
3495*11878SVenu.Iyer@Sun.COM 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3496*11878SVenu.Iyer@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv6_ah]);
3497*11878SVenu.Iyer@Sun.COM 
3498*11878SVenu.Iyer@Sun.COM 		value = (int)param_arr[param_class_opt_ipv6_ah].value;
3499*11878SVenu.Iyer@Sun.COM 	} else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
3500*11878SVenu.Iyer@Sun.COM 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3501*11878SVenu.Iyer@Sun.COM 		    (caddr_t)&param_arr[param_class_opt_ipv6_sctp]);
3502*11878SVenu.Iyer@Sun.COM 
3503*11878SVenu.Iyer@Sun.COM 		value = (int)param_arr[param_class_opt_ipv6_sctp].value;
35047584SQiyan.Sun@Sun.COM 	} else {
3505*11878SVenu.Iyer@Sun.COM 		err = EINVAL;
35067584SQiyan.Sun@Sun.COM 	}
35077584SQiyan.Sun@Sun.COM 
35087584SQiyan.Sun@Sun.COM 	if (err == 0) {
35097584SQiyan.Sun@Sun.COM 		(void) snprintf(valstr, sizeof (valstr), "0x%x", value);
35107584SQiyan.Sun@Sun.COM 
35117584SQiyan.Sun@Sun.COM 		strsize = (uint_t)strlen(valstr);
35127584SQiyan.Sun@Sun.COM 		if (pr_valsize < strsize) {
35137584SQiyan.Sun@Sun.COM 			err = ENOBUFS;
35147584SQiyan.Sun@Sun.COM 		} else {
35157584SQiyan.Sun@Sun.COM 			(void) strlcpy(pr_val, valstr, pr_valsize);
35167584SQiyan.Sun@Sun.COM 		}
35177584SQiyan.Sun@Sun.COM 	}
35187584SQiyan.Sun@Sun.COM 
35197584SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
35207584SQiyan.Sun@Sun.COM 	    "<== hxge_get_priv_prop: return %d", err));
35217584SQiyan.Sun@Sun.COM 
35227584SQiyan.Sun@Sun.COM 	return (err);
35237584SQiyan.Sun@Sun.COM }
35246349Sqs148142 /*
35256349Sqs148142  * Module loading and removing entry points.
35266349Sqs148142  */
35276349Sqs148142 DDI_DEFINE_STREAM_OPS(hxge_dev_ops, nulldev, nulldev, hxge_attach, hxge_detach,
35287918SQiyan.Sun@Sun.COM     nodev, NULL, D_MP, NULL, NULL);
35296349Sqs148142 
35306349Sqs148142 extern struct mod_ops mod_driverops;
35316349Sqs148142 
35326349Sqs148142 #define	HXGE_DESC_VER	"HXGE 10Gb Ethernet Driver"
35336349Sqs148142 
35346349Sqs148142 /*
35356349Sqs148142  * Module linkage information for the kernel.
35366349Sqs148142  */
35376349Sqs148142 static struct modldrv hxge_modldrv = {
35386349Sqs148142 	&mod_driverops,
35396349Sqs148142 	HXGE_DESC_VER,
35406349Sqs148142 	&hxge_dev_ops
35416349Sqs148142 };
35426349Sqs148142 
35436349Sqs148142 static struct modlinkage modlinkage = {
35446349Sqs148142 	MODREV_1, (void *) &hxge_modldrv, NULL
35456349Sqs148142 };
35466349Sqs148142 
35476349Sqs148142 int
_init(void)35486349Sqs148142 _init(void)
35496349Sqs148142 {
35506349Sqs148142 	int status;
35516349Sqs148142 
35526349Sqs148142 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init"));
35536349Sqs148142 	mac_init_ops(&hxge_dev_ops, "hxge");
35546349Sqs148142 	status = ddi_soft_state_init(&hxge_list, sizeof (hxge_t), 0);
35556349Sqs148142 	if (status != 0) {
35566349Sqs148142 		HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL,
35576349Sqs148142 		    "failed to init device soft state"));
35586349Sqs148142 		mac_fini_ops(&hxge_dev_ops);
35596349Sqs148142 		goto _init_exit;
35606349Sqs148142 	}
35616349Sqs148142 
35626349Sqs148142 	status = mod_install(&modlinkage);
35636349Sqs148142 	if (status != 0) {
35646349Sqs148142 		ddi_soft_state_fini(&hxge_list);
35656349Sqs148142 		HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, "Mod install failed"));
35666349Sqs148142 		goto _init_exit;
35676349Sqs148142 	}
35686349Sqs148142 
35696349Sqs148142 	MUTEX_INIT(&hxge_common_lock, NULL, MUTEX_DRIVER, NULL);
35706349Sqs148142 
35716349Sqs148142 _init_exit:
35726349Sqs148142 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status));
35736349Sqs148142 
35746349Sqs148142 	return (status);
35756349Sqs148142 }
35766349Sqs148142 
35776349Sqs148142 int
_fini(void)35786349Sqs148142 _fini(void)
35796349Sqs148142 {
35806349Sqs148142 	int status;
35816349Sqs148142 
35826349Sqs148142 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini"));
35836349Sqs148142 
35846349Sqs148142 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove"));
35856349Sqs148142 
35866349Sqs148142 	if (hxge_mblks_pending)
35876349Sqs148142 		return (EBUSY);
35886349Sqs148142 
35896349Sqs148142 	status = mod_remove(&modlinkage);
35906349Sqs148142 	if (status != DDI_SUCCESS) {
35916349Sqs148142 		HXGE_DEBUG_MSG((NULL, MOD_CTL,
35926349Sqs148142 		    "Module removal failed 0x%08x", status));
35936349Sqs148142 		goto _fini_exit;
35946349Sqs148142 	}
35956349Sqs148142 
35966349Sqs148142 	mac_fini_ops(&hxge_dev_ops);
35976349Sqs148142 
35986349Sqs148142 	ddi_soft_state_fini(&hxge_list);
35996349Sqs148142 
36006349Sqs148142 	MUTEX_DESTROY(&hxge_common_lock);
36016349Sqs148142 
36026349Sqs148142 _fini_exit:
36036349Sqs148142 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status));
36046349Sqs148142 
36056349Sqs148142 	return (status);
36066349Sqs148142 }
36076349Sqs148142 
36086349Sqs148142 int
_info(struct modinfo * modinfop)36096349Sqs148142 _info(struct modinfo *modinfop)
36106349Sqs148142 {
36116349Sqs148142 	int status;
36126349Sqs148142 
36136349Sqs148142 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info"));
36146349Sqs148142 	status = mod_info(&modlinkage, modinfop);
36156349Sqs148142 	HXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status));
36166349Sqs148142 
36176349Sqs148142 	return (status);
36186349Sqs148142 }
36196349Sqs148142 
36206349Sqs148142 /*ARGSUSED*/
362111257SMichael.Speer@Sun.COM static hxge_status_t
hxge_add_intrs(p_hxge_t hxgep)36226349Sqs148142 hxge_add_intrs(p_hxge_t hxgep)
36236349Sqs148142 {
36246349Sqs148142 	int		intr_types;
36256349Sqs148142 	int		type = 0;
36266349Sqs148142 	int		ddi_status = DDI_SUCCESS;
36276349Sqs148142 	hxge_status_t	status = HXGE_OK;
36286349Sqs148142 
36296349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs"));
36306349Sqs148142 
36316349Sqs148142 	hxgep->hxge_intr_type.intr_registered = B_FALSE;
36326349Sqs148142 	hxgep->hxge_intr_type.intr_enabled = B_FALSE;
36336349Sqs148142 	hxgep->hxge_intr_type.msi_intx_cnt = 0;
36346349Sqs148142 	hxgep->hxge_intr_type.intr_added = 0;
36356349Sqs148142 	hxgep->hxge_intr_type.niu_msi_enable = B_FALSE;
36366349Sqs148142 	hxgep->hxge_intr_type.intr_type = 0;
36376349Sqs148142 
36386349Sqs148142 	if (hxge_msi_enable) {
36396349Sqs148142 		hxgep->hxge_intr_type.niu_msi_enable = B_TRUE;
36406349Sqs148142 	}
36416349Sqs148142 
36426349Sqs148142 	/* Get the supported interrupt types */
36436349Sqs148142 	if ((ddi_status = ddi_intr_get_supported_types(hxgep->dip, &intr_types))
36446349Sqs148142 	    != DDI_SUCCESS) {
36456349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_intrs: "
36466349Sqs148142 		    "ddi_intr_get_supported_types failed: status 0x%08x",
36476349Sqs148142 		    ddi_status));
36486349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
36496349Sqs148142 	}
36506349Sqs148142 
36516349Sqs148142 	hxgep->hxge_intr_type.intr_types = intr_types;
36526349Sqs148142 
36536349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
36546349Sqs148142 	    "ddi_intr_get_supported_types: 0x%08x", intr_types));
36556349Sqs148142 
36566349Sqs148142 	/*
36576349Sqs148142 	 * Pick the interrupt type to use MSIX, MSI, INTX hxge_msi_enable:
36586349Sqs148142 	 *	(1): 1 - MSI
36596349Sqs148142 	 *	(2): 2 - MSI-X
36606349Sqs148142 	 *	others - FIXED
36616349Sqs148142 	 */
36626349Sqs148142 	switch (hxge_msi_enable) {
36636349Sqs148142 	default:
36646349Sqs148142 		type = DDI_INTR_TYPE_FIXED;
36656349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
36666349Sqs148142 		    "use fixed (intx emulation) type %08x", type));
36676349Sqs148142 		break;
36686349Sqs148142 
36696349Sqs148142 	case 2:
36706349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
36716349Sqs148142 		    "ddi_intr_get_supported_types: 0x%08x", intr_types));
36726349Sqs148142 		if (intr_types & DDI_INTR_TYPE_MSIX) {
36736349Sqs148142 			type = DDI_INTR_TYPE_MSIX;
36746349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
36756349Sqs148142 			    "==> hxge_add_intrs: "
36766349Sqs148142 			    "ddi_intr_get_supported_types: MSIX 0x%08x", type));
36776349Sqs148142 		} else if (intr_types & DDI_INTR_TYPE_MSI) {
36786349Sqs148142 			type = DDI_INTR_TYPE_MSI;
36796349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
36806349Sqs148142 			    "==> hxge_add_intrs: "
36816349Sqs148142 			    "ddi_intr_get_supported_types: MSI 0x%08x", type));
36826349Sqs148142 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
36836349Sqs148142 			type = DDI_INTR_TYPE_FIXED;
36846349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
36856349Sqs148142 			    "ddi_intr_get_supported_types: MSXED0x%08x", type));
36866349Sqs148142 		}
36876349Sqs148142 		break;
36886349Sqs148142 
36896349Sqs148142 	case 1:
36906349Sqs148142 		if (intr_types & DDI_INTR_TYPE_MSI) {
36916349Sqs148142 			type = DDI_INTR_TYPE_MSI;
36926349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
36936349Sqs148142 			    "==> hxge_add_intrs: "
36946349Sqs148142 			    "ddi_intr_get_supported_types: MSI 0x%08x", type));
36956349Sqs148142 		} else if (intr_types & DDI_INTR_TYPE_MSIX) {
36966349Sqs148142 			type = DDI_INTR_TYPE_MSIX;
36976349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
36986349Sqs148142 			    "==> hxge_add_intrs: "
36996349Sqs148142 			    "ddi_intr_get_supported_types: MSIX 0x%08x", type));
37006349Sqs148142 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
37016349Sqs148142 			type = DDI_INTR_TYPE_FIXED;
37026349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
37036349Sqs148142 			    "==> hxge_add_intrs: "
37046349Sqs148142 			    "ddi_intr_get_supported_types: MSXED0x%08x", type));
37056349Sqs148142 		}
37066349Sqs148142 	}
37076349Sqs148142 
37086349Sqs148142 	hxgep->hxge_intr_type.intr_type = type;
37096349Sqs148142 	if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI ||
37106349Sqs148142 	    type == DDI_INTR_TYPE_FIXED) &&
37116349Sqs148142 	    hxgep->hxge_intr_type.niu_msi_enable) {
37126349Sqs148142 		if ((status = hxge_add_intrs_adv(hxgep)) != DDI_SUCCESS) {
37136349Sqs148142 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
37146349Sqs148142 			    " hxge_add_intrs: "
37156349Sqs148142 			    " hxge_add_intrs_adv failed: status 0x%08x",
37166349Sqs148142 			    status));
37176349Sqs148142 			return (status);
37186349Sqs148142 		} else {
37196349Sqs148142 			HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_intrs: "
37206349Sqs148142 			    "interrupts registered : type %d", type));
37216349Sqs148142 			hxgep->hxge_intr_type.intr_registered = B_TRUE;
37226349Sqs148142 
37236349Sqs148142 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
37246349Sqs148142 			    "\nAdded advanced hxge add_intr_adv "
37256349Sqs148142 			    "intr type 0x%x\n", type));
37266349Sqs148142 
37276349Sqs148142 			return (status);
37286349Sqs148142 		}
37296349Sqs148142 	}
37306349Sqs148142 
37316349Sqs148142 	if (!hxgep->hxge_intr_type.intr_registered) {
37326349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
37336349Sqs148142 		    "==> hxge_add_intrs: failed to register interrupts"));
37346349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
37356349Sqs148142 	}
37366349Sqs148142 
37376349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs"));
37386349Sqs148142 
37396349Sqs148142 	return (status);
37406349Sqs148142 }
37416349Sqs148142 
37426349Sqs148142 /*ARGSUSED*/
37436349Sqs148142 static hxge_status_t
hxge_add_intrs_adv(p_hxge_t hxgep)37446349Sqs148142 hxge_add_intrs_adv(p_hxge_t hxgep)
37456349Sqs148142 {
37466349Sqs148142 	int		intr_type;
37476349Sqs148142 	p_hxge_intr_t	intrp;
37486349Sqs148142 	hxge_status_t	status;
37496349Sqs148142 
37506349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv"));
37516349Sqs148142 
37526349Sqs148142 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
37536349Sqs148142 	intr_type = intrp->intr_type;
37546349Sqs148142 
37556349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv: type 0x%x",
37566349Sqs148142 	    intr_type));
37576349Sqs148142 
37586349Sqs148142 	switch (intr_type) {
37596349Sqs148142 	case DDI_INTR_TYPE_MSI:		/* 0x2 */
37606349Sqs148142 	case DDI_INTR_TYPE_MSIX:	/* 0x4 */
37616349Sqs148142 		status = hxge_add_intrs_adv_type(hxgep, intr_type);
37626349Sqs148142 		break;
37636349Sqs148142 
37646349Sqs148142 	case DDI_INTR_TYPE_FIXED:	/* 0x1 */
37656349Sqs148142 		status = hxge_add_intrs_adv_type_fix(hxgep, intr_type);
37666349Sqs148142 		break;
37676349Sqs148142 
37686349Sqs148142 	default:
37696349Sqs148142 		status = HXGE_ERROR;
37706349Sqs148142 		break;
37716349Sqs148142 	}
37726349Sqs148142 
37736349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv"));
37746349Sqs148142 
37756349Sqs148142 	return (status);
37766349Sqs148142 }
37776349Sqs148142 
37786349Sqs148142 /*ARGSUSED*/
37796349Sqs148142 static hxge_status_t
hxge_add_intrs_adv_type(p_hxge_t hxgep,uint32_t int_type)37806349Sqs148142 hxge_add_intrs_adv_type(p_hxge_t hxgep, uint32_t int_type)
37816349Sqs148142 {
37826349Sqs148142 	dev_info_t	*dip = hxgep->dip;
37836349Sqs148142 	p_hxge_ldg_t	ldgp;
37846349Sqs148142 	p_hxge_intr_t	intrp;
37856349Sqs148142 	uint_t		*inthandler;
37866349Sqs148142 	void		*arg1, *arg2;
37876349Sqs148142 	int		behavior;
37886349Sqs148142 	int		nintrs, navail;
37898366SQiyan.Sun@Sun.COM 	int		nactual, nrequired, nrequest;
37906349Sqs148142 	int		inum = 0;
37916349Sqs148142 	int		loop = 0;
37926349Sqs148142 	int		x, y;
37936349Sqs148142 	int		ddi_status = DDI_SUCCESS;
37946349Sqs148142 	hxge_status_t	status = HXGE_OK;
37956349Sqs148142 
37966349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type"));
37976349Sqs148142 
37986349Sqs148142 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
37996349Sqs148142 
38006349Sqs148142 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
38016349Sqs148142 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
38026349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38036349Sqs148142 		    "ddi_intr_get_nintrs() failed, status: 0x%x%, "
38046349Sqs148142 		    "nintrs: %d", ddi_status, nintrs));
38056349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
38066349Sqs148142 	}
38076349Sqs148142 
38086349Sqs148142 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
38096349Sqs148142 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
38106349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38116349Sqs148142 		    "ddi_intr_get_navail() failed, status: 0x%x%, "
38126349Sqs148142 		    "nintrs: %d", ddi_status, navail));
38136349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
38146349Sqs148142 	}
38156349Sqs148142 
38166349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
38176349Sqs148142 	    "ddi_intr_get_navail() returned: intr type %d nintrs %d, navail %d",
38186349Sqs148142 	    int_type, nintrs, navail));
38196349Sqs148142 
38208366SQiyan.Sun@Sun.COM 	/* PSARC/2007/453 MSI-X interrupt limit override */
38218366SQiyan.Sun@Sun.COM 	if (int_type == DDI_INTR_TYPE_MSIX) {
38228366SQiyan.Sun@Sun.COM 		nrequest = hxge_create_msi_property(hxgep);
38238366SQiyan.Sun@Sun.COM 		if (nrequest < navail) {
38248366SQiyan.Sun@Sun.COM 			navail = nrequest;
38258366SQiyan.Sun@Sun.COM 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
38268366SQiyan.Sun@Sun.COM 			    "hxge_add_intrs_adv_type: nintrs %d "
38278366SQiyan.Sun@Sun.COM 			    "navail %d (nrequest %d)",
38288366SQiyan.Sun@Sun.COM 			    nintrs, navail, nrequest));
38298366SQiyan.Sun@Sun.COM 		}
38308366SQiyan.Sun@Sun.COM 	}
38318366SQiyan.Sun@Sun.COM 
38326349Sqs148142 	if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) {
38336349Sqs148142 		/* MSI must be power of 2 */
38346349Sqs148142 		if ((navail & 16) == 16) {
38356349Sqs148142 			navail = 16;
38366349Sqs148142 		} else if ((navail & 8) == 8) {
38376349Sqs148142 			navail = 8;
38386349Sqs148142 		} else if ((navail & 4) == 4) {
38396349Sqs148142 			navail = 4;
38406349Sqs148142 		} else if ((navail & 2) == 2) {
38416349Sqs148142 			navail = 2;
38426349Sqs148142 		} else {
38436349Sqs148142 			navail = 1;
38446349Sqs148142 		}
38456349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
38466349Sqs148142 		    "ddi_intr_get_navail(): (msi power of 2) nintrs %d, "
38476349Sqs148142 		    "navail %d", nintrs, navail));
38486349Sqs148142 	}
38496349Sqs148142 
38506349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
38516349Sqs148142 	    "requesting: intr type %d nintrs %d, navail %d",
38526349Sqs148142 	    int_type, nintrs, navail));
38536349Sqs148142 
38546349Sqs148142 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
38556349Sqs148142 	    DDI_INTR_ALLOC_NORMAL);
38566349Sqs148142 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
38576349Sqs148142 	intrp->htable = kmem_zalloc(intrp->intr_size, KM_SLEEP);
38586349Sqs148142 
38596349Sqs148142 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
38606349Sqs148142 	    navail, &nactual, behavior);
38616349Sqs148142 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
38626349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38636349Sqs148142 		    " ddi_intr_alloc() failed: %d", ddi_status));
38646349Sqs148142 		kmem_free(intrp->htable, intrp->intr_size);
38656349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
38666349Sqs148142 	}
38676349Sqs148142 
38686349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
38696349Sqs148142 	    "ddi_intr_alloc() returned: navail %d nactual %d",
38706349Sqs148142 	    navail, nactual));
38716349Sqs148142 
38726349Sqs148142 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
38736349Sqs148142 	    (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
38746349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38756349Sqs148142 		    " ddi_intr_get_pri() failed: %d", ddi_status));
38766349Sqs148142 		/* Free already allocated interrupts */
38776349Sqs148142 		for (y = 0; y < nactual; y++) {
38786349Sqs148142 			(void) ddi_intr_free(intrp->htable[y]);
38796349Sqs148142 		}
38806349Sqs148142 
38816349Sqs148142 		kmem_free(intrp->htable, intrp->intr_size);
38826349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
38836349Sqs148142 	}
38846349Sqs148142 
38856349Sqs148142 	nrequired = 0;
38866349Sqs148142 	status = hxge_ldgv_init(hxgep, &nactual, &nrequired);
38876349Sqs148142 	if (status != HXGE_OK) {
38886349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38896349Sqs148142 		    "hxge_add_intrs_adv_typ:hxge_ldgv_init "
38906349Sqs148142 		    "failed: 0x%x", status));
38916349Sqs148142 		/* Free already allocated interrupts */
38926349Sqs148142 		for (y = 0; y < nactual; y++) {
38936349Sqs148142 			(void) ddi_intr_free(intrp->htable[y]);
38946349Sqs148142 		}
38956349Sqs148142 
38966349Sqs148142 		kmem_free(intrp->htable, intrp->intr_size);
38976349Sqs148142 		return (status);
38986349Sqs148142 	}
38996349Sqs148142 
39006349Sqs148142 	ldgp = hxgep->ldgvp->ldgp;
39016349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
39026349Sqs148142 	    "After hxge_ldgv_init(): nreq %d nactual %d", nrequired, nactual));
39036349Sqs148142 
39046349Sqs148142 	if (nactual < nrequired)
39056349Sqs148142 		loop = nactual;
39066349Sqs148142 	else
39076349Sqs148142 		loop = nrequired;
39086349Sqs148142 
39096349Sqs148142 	for (x = 0; x < loop; x++, ldgp++) {
39106349Sqs148142 		ldgp->vector = (uint8_t)x;
39116349Sqs148142 		arg1 = ldgp->ldvp;
39126349Sqs148142 		arg2 = hxgep;
39136349Sqs148142 		if (ldgp->nldvs == 1) {
39146349Sqs148142 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
39156349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
39166349Sqs148142 			    "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: "
39176349Sqs148142 			    "1-1 int handler (entry %d)\n",
39186349Sqs148142 			    arg1, arg2, x));
39196349Sqs148142 		} else if (ldgp->nldvs > 1) {
39206349Sqs148142 			inthandler = (uint_t *)ldgp->sys_intr_handler;
39216349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
39226349Sqs148142 			    "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: "
39236349Sqs148142 			    "nldevs %d int handler (entry %d)\n",
39246349Sqs148142 			    arg1, arg2, ldgp->nldvs, x));
39256349Sqs148142 		}
39266349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
39276349Sqs148142 		    "==> hxge_add_intrs_adv_type: ddi_add_intr(inum) #%d "
39286349Sqs148142 		    "htable 0x%llx", x, intrp->htable[x]));
39296349Sqs148142 
39306349Sqs148142 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
39316349Sqs148142 		    (ddi_intr_handler_t *)inthandler, arg1, arg2)) !=
39326349Sqs148142 		    DDI_SUCCESS) {
39336349Sqs148142 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
39346349Sqs148142 			    "==> hxge_add_intrs_adv_type: failed #%d "
39356349Sqs148142 			    "status 0x%x", x, ddi_status));
39366349Sqs148142 			for (y = 0; y < intrp->intr_added; y++) {
39376349Sqs148142 				(void) ddi_intr_remove_handler(
39386349Sqs148142 				    intrp->htable[y]);
39396349Sqs148142 			}
39406349Sqs148142 
39416349Sqs148142 			/* Free already allocated intr */
39426349Sqs148142 			for (y = 0; y < nactual; y++) {
39436349Sqs148142 				(void) ddi_intr_free(intrp->htable[y]);
39446349Sqs148142 			}
39456349Sqs148142 			kmem_free(intrp->htable, intrp->intr_size);
39466349Sqs148142 
39476349Sqs148142 			(void) hxge_ldgv_uninit(hxgep);
39486349Sqs148142 
39496349Sqs148142 			return (HXGE_ERROR | HXGE_DDI_FAILED);
39506349Sqs148142 		}
39516349Sqs148142 
3952*11878SVenu.Iyer@Sun.COM 		ldgp->htable_idx = x;
39536349Sqs148142 		intrp->intr_added++;
39546349Sqs148142 	}
39556349Sqs148142 	intrp->msi_intx_cnt = nactual;
39566349Sqs148142 
39576349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
39586349Sqs148142 	    "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d",
39596349Sqs148142 	    navail, nactual, intrp->msi_intx_cnt, intrp->intr_added));
39606349Sqs148142 
39616349Sqs148142 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
39626349Sqs148142 	(void) hxge_intr_ldgv_init(hxgep);
39636349Sqs148142 
39646349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type"));
39656349Sqs148142 
39666349Sqs148142 	return (status);
39676349Sqs148142 }
39686349Sqs148142 
39696349Sqs148142 /*ARGSUSED*/
39706349Sqs148142 static hxge_status_t
hxge_add_intrs_adv_type_fix(p_hxge_t hxgep,uint32_t int_type)39716349Sqs148142 hxge_add_intrs_adv_type_fix(p_hxge_t hxgep, uint32_t int_type)
39726349Sqs148142 {
39736349Sqs148142 	dev_info_t	*dip = hxgep->dip;
39746349Sqs148142 	p_hxge_ldg_t	ldgp;
39756349Sqs148142 	p_hxge_intr_t	intrp;
39766349Sqs148142 	uint_t		*inthandler;
39776349Sqs148142 	void		*arg1, *arg2;
39786349Sqs148142 	int		behavior;
39796349Sqs148142 	int		nintrs, navail;
39806349Sqs148142 	int		nactual, nrequired;
39816349Sqs148142 	int		inum = 0;
39826349Sqs148142 	int		x, y;
39836349Sqs148142 	int		ddi_status = DDI_SUCCESS;
39846349Sqs148142 	hxge_status_t	status = HXGE_OK;
39856349Sqs148142 
39866349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type_fix"));
39876349Sqs148142 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
39886349Sqs148142 
39896349Sqs148142 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
39906349Sqs148142 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
39916349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
39926349Sqs148142 		    "ddi_intr_get_nintrs() failed, status: 0x%x%, "
39936349Sqs148142 		    "nintrs: %d", status, nintrs));
39946349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
39956349Sqs148142 	}
39966349Sqs148142 
39976349Sqs148142 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
39986349Sqs148142 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
39996349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
40006349Sqs148142 		    "ddi_intr_get_navail() failed, status: 0x%x%, "
40016349Sqs148142 		    "nintrs: %d", ddi_status, navail));
40026349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
40036349Sqs148142 	}
40046349Sqs148142 
40056349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
40066349Sqs148142 	    "ddi_intr_get_navail() returned: nintrs %d, naavail %d",
40076349Sqs148142 	    nintrs, navail));
40086349Sqs148142 
40096349Sqs148142 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
40106349Sqs148142 	    DDI_INTR_ALLOC_NORMAL);
40116349Sqs148142 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
40126349Sqs148142 	intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
40136349Sqs148142 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
40146349Sqs148142 	    navail, &nactual, behavior);
40156349Sqs148142 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
40166349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
40176349Sqs148142 		    " ddi_intr_alloc() failed: %d", ddi_status));
40186349Sqs148142 		kmem_free(intrp->htable, intrp->intr_size);
40196349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
40206349Sqs148142 	}
40216349Sqs148142 
40226349Sqs148142 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
40236349Sqs148142 	    (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
40246349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
40256349Sqs148142 		    " ddi_intr_get_pri() failed: %d", ddi_status));
40266349Sqs148142 		/* Free already allocated interrupts */
40276349Sqs148142 		for (y = 0; y < nactual; y++) {
40286349Sqs148142 			(void) ddi_intr_free(intrp->htable[y]);
40296349Sqs148142 		}
40306349Sqs148142 
40316349Sqs148142 		kmem_free(intrp->htable, intrp->intr_size);
40326349Sqs148142 		return (HXGE_ERROR | HXGE_DDI_FAILED);
40336349Sqs148142 	}
40346349Sqs148142 
40356349Sqs148142 	nrequired = 0;
40366349Sqs148142 	status = hxge_ldgv_init(hxgep, &nactual, &nrequired);
40376349Sqs148142 	if (status != HXGE_OK) {
40386349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
40396349Sqs148142 		    "hxge_add_intrs_adv_type_fix:hxge_ldgv_init "
40406349Sqs148142 		    "failed: 0x%x", status));
40416349Sqs148142 		/* Free already allocated interrupts */
40426349Sqs148142 		for (y = 0; y < nactual; y++) {
40436349Sqs148142 			(void) ddi_intr_free(intrp->htable[y]);
40446349Sqs148142 		}
40456349Sqs148142 
40466349Sqs148142 		kmem_free(intrp->htable, intrp->intr_size);
40476349Sqs148142 		return (status);
40486349Sqs148142 	}
40496349Sqs148142 
40506349Sqs148142 	ldgp = hxgep->ldgvp->ldgp;
40516349Sqs148142 	for (x = 0; x < nrequired; x++, ldgp++) {
40526349Sqs148142 		ldgp->vector = (uint8_t)x;
40536349Sqs148142 		arg1 = ldgp->ldvp;
40546349Sqs148142 		arg2 = hxgep;
40556349Sqs148142 		if (ldgp->nldvs == 1) {
40566349Sqs148142 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
40576349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
40586349Sqs148142 			    "hxge_add_intrs_adv_type_fix: "
40596349Sqs148142 			    "1-1 int handler(%d) ldg %d ldv %d "
40606349Sqs148142 			    "arg1 $%p arg2 $%p\n",
40616349Sqs148142 			    x, ldgp->ldg, ldgp->ldvp->ldv, arg1, arg2));
40626349Sqs148142 		} else if (ldgp->nldvs > 1) {
40636349Sqs148142 			inthandler = (uint_t *)ldgp->sys_intr_handler;
40646349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
40656349Sqs148142 			    "hxge_add_intrs_adv_type_fix: "
40666349Sqs148142 			    "shared ldv %d int handler(%d) ldv %d ldg %d"
40676349Sqs148142 			    "arg1 0x%016llx arg2 0x%016llx\n",
40686349Sqs148142 			    x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv,
40696349Sqs148142 			    arg1, arg2));
40706349Sqs148142 		}
40716349Sqs148142 
40726349Sqs148142 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
40736349Sqs148142 		    (ddi_intr_handler_t *)inthandler, arg1, arg2)) !=
40746349Sqs148142 		    DDI_SUCCESS) {
40756349Sqs148142 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
40766349Sqs148142 			    "==> hxge_add_intrs_adv_type_fix: failed #%d "
40776349Sqs148142 			    "status 0x%x", x, ddi_status));
40786349Sqs148142 			for (y = 0; y < intrp->intr_added; y++) {
40796349Sqs148142 				(void) ddi_intr_remove_handler(
40806349Sqs148142 				    intrp->htable[y]);
40816349Sqs148142 			}
40826349Sqs148142 			for (y = 0; y < nactual; y++) {
40836349Sqs148142 				(void) ddi_intr_free(intrp->htable[y]);
40846349Sqs148142 			}
40856349Sqs148142 			/* Free already allocated intr */
40866349Sqs148142 			kmem_free(intrp->htable, intrp->intr_size);
40876349Sqs148142 
40886349Sqs148142 			(void) hxge_ldgv_uninit(hxgep);
40896349Sqs148142 
40906349Sqs148142 			return (HXGE_ERROR | HXGE_DDI_FAILED);
40916349Sqs148142 		}
40926349Sqs148142 		intrp->intr_added++;
40936349Sqs148142 	}
40946349Sqs148142 
40956349Sqs148142 	intrp->msi_intx_cnt = nactual;
40966349Sqs148142 
40976349Sqs148142 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
40986349Sqs148142 
40996349Sqs148142 	status = hxge_intr_ldgv_init(hxgep);
41006349Sqs148142 
41016349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type_fix"));
41026349Sqs148142 
41036349Sqs148142 	return (status);
41046349Sqs148142 }
41056349Sqs148142 
41066349Sqs148142 /*ARGSUSED*/
41076349Sqs148142 static void
hxge_remove_intrs(p_hxge_t hxgep)41086349Sqs148142 hxge_remove_intrs(p_hxge_t hxgep)
41096349Sqs148142 {
41106349Sqs148142 	int		i, inum;
41116349Sqs148142 	p_hxge_intr_t	intrp;
41126349Sqs148142 
41136349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs"));
41146349Sqs148142 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
41156349Sqs148142 	if (!intrp->intr_registered) {
41166349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
41176349Sqs148142 		    "<== hxge_remove_intrs: interrupts not registered"));
41186349Sqs148142 		return;
41196349Sqs148142 	}
41206349Sqs148142 
41216349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs:advanced"));
41226349Sqs148142 
41236349Sqs148142 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
41246349Sqs148142 		(void) ddi_intr_block_disable(intrp->htable,
41256349Sqs148142 		    intrp->intr_added);
41266349Sqs148142 	} else {
41276349Sqs148142 		for (i = 0; i < intrp->intr_added; i++) {
41286349Sqs148142 			(void) ddi_intr_disable(intrp->htable[i]);
41296349Sqs148142 		}
41306349Sqs148142 	}
41316349Sqs148142 
41326349Sqs148142 	for (inum = 0; inum < intrp->intr_added; inum++) {
41336349Sqs148142 		if (intrp->htable[inum]) {
41346349Sqs148142 			(void) ddi_intr_remove_handler(intrp->htable[inum]);
41356349Sqs148142 		}
41366349Sqs148142 	}
41376349Sqs148142 
41386349Sqs148142 	for (inum = 0; inum < intrp->msi_intx_cnt; inum++) {
41396349Sqs148142 		if (intrp->htable[inum]) {
41406349Sqs148142 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
41416349Sqs148142 			    "hxge_remove_intrs: ddi_intr_free inum %d "
41426349Sqs148142 			    "msi_intx_cnt %d intr_added %d",
41436349Sqs148142 			    inum, intrp->msi_intx_cnt, intrp->intr_added));
41446349Sqs148142 
41456349Sqs148142 			(void) ddi_intr_free(intrp->htable[inum]);
41466349Sqs148142 		}
41476349Sqs148142 	}
41486349Sqs148142 
41496349Sqs148142 	kmem_free(intrp->htable, intrp->intr_size);
41506349Sqs148142 	intrp->intr_registered = B_FALSE;
41516349Sqs148142 	intrp->intr_enabled = B_FALSE;
41526349Sqs148142 	intrp->msi_intx_cnt = 0;
41536349Sqs148142 	intrp->intr_added = 0;
41546349Sqs148142 
41556349Sqs148142 	(void) hxge_ldgv_uninit(hxgep);
41566349Sqs148142 
41576349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_intrs"));
41586349Sqs148142 }
41596349Sqs148142 
41606349Sqs148142 /*ARGSUSED*/
416111257SMichael.Speer@Sun.COM static void
hxge_intrs_enable(p_hxge_t hxgep)41626349Sqs148142 hxge_intrs_enable(p_hxge_t hxgep)
41636349Sqs148142 {
41646349Sqs148142 	p_hxge_intr_t	intrp;
41656349Sqs148142 	int		i;
41666349Sqs148142 	int		status;
41676349Sqs148142 
41686349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable"));
41696349Sqs148142 
41706349Sqs148142 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
41716349Sqs148142 
41726349Sqs148142 	if (!intrp->intr_registered) {
41736349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_intrs_enable: "
41746349Sqs148142 		    "interrupts are not registered"));
41756349Sqs148142 		return;
41766349Sqs148142 	}
41776349Sqs148142 
41786349Sqs148142 	if (intrp->intr_enabled) {
41796349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
41806349Sqs148142 		    "<== hxge_intrs_enable: already enabled"));
41816349Sqs148142 		return;
41826349Sqs148142 	}
41836349Sqs148142 
41846349Sqs148142 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
41856349Sqs148142 		status = ddi_intr_block_enable(intrp->htable,
41866349Sqs148142 		    intrp->intr_added);
41876349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable "
41886349Sqs148142 		    "block enable - status 0x%x total inums #%d\n",
41896349Sqs148142 		    status, intrp->intr_added));
41906349Sqs148142 	} else {
41916349Sqs148142 		for (i = 0; i < intrp->intr_added; i++) {
41926349Sqs148142 			status = ddi_intr_enable(intrp->htable[i]);
41936349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable "
41946349Sqs148142 			    "ddi_intr_enable:enable - status 0x%x "
41956349Sqs148142 			    "total inums %d enable inum #%d\n",
41966349Sqs148142 			    status, intrp->intr_added, i));
41976349Sqs148142 			if (status == DDI_SUCCESS) {
41986349Sqs148142 				intrp->intr_enabled = B_TRUE;
41996349Sqs148142 			}
42006349Sqs148142 		}
42016349Sqs148142 	}
42026349Sqs148142 
42036349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_enable"));
42046349Sqs148142 }
42056349Sqs148142 
42066349Sqs148142 /*ARGSUSED*/
42076349Sqs148142 static void
hxge_intrs_disable(p_hxge_t hxgep)42086349Sqs148142 hxge_intrs_disable(p_hxge_t hxgep)
42096349Sqs148142 {
42106349Sqs148142 	p_hxge_intr_t	intrp;
42116349Sqs148142 	int		i;
42126349Sqs148142 
42136349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_disable"));
42146349Sqs148142 
42156349Sqs148142 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
42166349Sqs148142 
42176349Sqs148142 	if (!intrp->intr_registered) {
42186349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable: "
42196349Sqs148142 		    "interrupts are not registered"));
42206349Sqs148142 		return;
42216349Sqs148142 	}
42226349Sqs148142 
42236349Sqs148142 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
42246349Sqs148142 		(void) ddi_intr_block_disable(intrp->htable,
42256349Sqs148142 		    intrp->intr_added);
42266349Sqs148142 	} else {
42276349Sqs148142 		for (i = 0; i < intrp->intr_added; i++) {
42286349Sqs148142 			(void) ddi_intr_disable(intrp->htable[i]);
42296349Sqs148142 		}
42306349Sqs148142 	}
42316349Sqs148142 
42326349Sqs148142 	intrp->intr_enabled = B_FALSE;
42336349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable"));
42346349Sqs148142 }
42356349Sqs148142 
42366349Sqs148142 static hxge_status_t
hxge_mac_register(p_hxge_t hxgep)42376349Sqs148142 hxge_mac_register(p_hxge_t hxgep)
42386349Sqs148142 {
42396349Sqs148142 	mac_register_t	*macp;
42406349Sqs148142 	int		status;
42416349Sqs148142 
42426349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_mac_register"));
42436349Sqs148142 
42446349Sqs148142 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
42456349Sqs148142 		return (HXGE_ERROR);
42466349Sqs148142 
42476349Sqs148142 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
42486349Sqs148142 	macp->m_driver = hxgep;
42496349Sqs148142 	macp->m_dip = hxgep->dip;
42506349Sqs148142 	macp->m_src_addr = hxgep->ouraddr.ether_addr_octet;
42518718SMichael.Speer@Sun.COM 	macp->m_callbacks = &hxge_m_callbacks;
42528718SMichael.Speer@Sun.COM 	macp->m_min_sdu = 0;
42538718SMichael.Speer@Sun.COM 	macp->m_max_sdu = hxgep->vmac.maxframesize - MTU_TO_FRAME_SIZE;
42548718SMichael.Speer@Sun.COM 	macp->m_margin = VLAN_TAGSZ;
42558718SMichael.Speer@Sun.COM 	macp->m_priv_props = hxge_priv_props;
42568718SMichael.Speer@Sun.COM 	macp->m_v12n = MAC_VIRT_LEVEL1;
42576349Sqs148142 
42586349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
42596349Sqs148142 	    "hxge_mac_register: ether addr is %x:%x:%x:%x:%x:%x",
42606349Sqs148142 	    macp->m_src_addr[0],
42616349Sqs148142 	    macp->m_src_addr[1],
42626349Sqs148142 	    macp->m_src_addr[2],
42636349Sqs148142 	    macp->m_src_addr[3],
42646349Sqs148142 	    macp->m_src_addr[4],
42656349Sqs148142 	    macp->m_src_addr[5]));
42666349Sqs148142 
42676349Sqs148142 	status = mac_register(macp, &hxgep->mach);
42686349Sqs148142 	mac_free(macp);
42696349Sqs148142 
42706349Sqs148142 	if (status != 0) {
42716349Sqs148142 		cmn_err(CE_WARN,
42726349Sqs148142 		    "hxge_mac_register failed (status %d instance %d)",
42736349Sqs148142 		    status, hxgep->instance);
42746349Sqs148142 		return (HXGE_ERROR);
42756349Sqs148142 	}
42766349Sqs148142 
42776349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_mac_register success "
42786349Sqs148142 	    "(instance %d)", hxgep->instance));
42796349Sqs148142 
42806349Sqs148142 	return (HXGE_OK);
42816349Sqs148142 }
42826349Sqs148142 
42836349Sqs148142 static int
hxge_init_common_dev(p_hxge_t hxgep)42846349Sqs148142 hxge_init_common_dev(p_hxge_t hxgep)
42856349Sqs148142 {
42866349Sqs148142 	p_hxge_hw_list_t	hw_p;
42876349Sqs148142 	dev_info_t		*p_dip;
42886349Sqs148142 
42896349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_init_common_dev"));
42906349Sqs148142 
42916349Sqs148142 	p_dip = hxgep->p_dip;
42926349Sqs148142 	MUTEX_ENTER(&hxge_common_lock);
42936349Sqs148142 
42946349Sqs148142 	/*
42956349Sqs148142 	 * Loop through existing per Hydra hardware list.
42966349Sqs148142 	 */
42976349Sqs148142 	for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) {
42986349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
42996349Sqs148142 		    "==> hxge_init_common_dev: hw_p $%p parent dip $%p",
43006349Sqs148142 		    hw_p, p_dip));
43016349Sqs148142 		if (hw_p->parent_devp == p_dip) {
43026349Sqs148142 			hxgep->hxge_hw_p = hw_p;
43036349Sqs148142 			hw_p->ndevs++;
43046349Sqs148142 			hw_p->hxge_p = hxgep;
43056349Sqs148142 			HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43066349Sqs148142 			    "==> hxge_init_common_device: "
43076349Sqs148142 			    "hw_p $%p parent dip $%p ndevs %d (found)",
43086349Sqs148142 			    hw_p, p_dip, hw_p->ndevs));
43096349Sqs148142 			break;
43106349Sqs148142 		}
43116349Sqs148142 	}
43126349Sqs148142 
43136349Sqs148142 	if (hw_p == NULL) {
43146349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43156349Sqs148142 		    "==> hxge_init_common_dev: parent dip $%p (new)", p_dip));
43166349Sqs148142 		hw_p = kmem_zalloc(sizeof (hxge_hw_list_t), KM_SLEEP);
43176349Sqs148142 		hw_p->parent_devp = p_dip;
43186349Sqs148142 		hw_p->magic = HXGE_MAGIC;
43196349Sqs148142 		hxgep->hxge_hw_p = hw_p;
43206349Sqs148142 		hw_p->ndevs++;
43216349Sqs148142 		hw_p->hxge_p = hxgep;
43226349Sqs148142 		hw_p->next = hxge_hw_list;
43236349Sqs148142 
43246349Sqs148142 		MUTEX_INIT(&hw_p->hxge_cfg_lock, NULL, MUTEX_DRIVER, NULL);
43256349Sqs148142 		MUTEX_INIT(&hw_p->hxge_tcam_lock, NULL, MUTEX_DRIVER, NULL);
43266349Sqs148142 		MUTEX_INIT(&hw_p->hxge_vlan_lock, NULL, MUTEX_DRIVER, NULL);
43276349Sqs148142 
43286349Sqs148142 		hxge_hw_list = hw_p;
43296349Sqs148142 	}
43306349Sqs148142 	MUTEX_EXIT(&hxge_common_lock);
43316349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43326349Sqs148142 	    "==> hxge_init_common_dev (hxge_hw_list) $%p", hxge_hw_list));
43336349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<== hxge_init_common_dev"));
43346349Sqs148142 
43356349Sqs148142 	return (HXGE_OK);
43366349Sqs148142 }
43376349Sqs148142 
43386349Sqs148142 static void
hxge_uninit_common_dev(p_hxge_t hxgep)43396349Sqs148142 hxge_uninit_common_dev(p_hxge_t hxgep)
43406349Sqs148142 {
43416349Sqs148142 	p_hxge_hw_list_t	hw_p, h_hw_p;
43426349Sqs148142 	dev_info_t		*p_dip;
43436349Sqs148142 
43446349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_uninit_common_dev"));
43456349Sqs148142 	if (hxgep->hxge_hw_p == NULL) {
43466349Sqs148142 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43476349Sqs148142 		    "<== hxge_uninit_common_dev (no common)"));
43486349Sqs148142 		return;
43496349Sqs148142 	}
43506349Sqs148142 
43516349Sqs148142 	MUTEX_ENTER(&hxge_common_lock);
43526349Sqs148142 	h_hw_p = hxge_hw_list;
43536349Sqs148142 	for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) {
43546349Sqs148142 		p_dip = hw_p->parent_devp;
43556349Sqs148142 		if (hxgep->hxge_hw_p == hw_p && p_dip == hxgep->p_dip &&
43566349Sqs148142 		    hxgep->hxge_hw_p->magic == HXGE_MAGIC &&
43576349Sqs148142 		    hw_p->magic == HXGE_MAGIC) {
43586349Sqs148142 			HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43596349Sqs148142 			    "==> hxge_uninit_common_dev: "
43606349Sqs148142 			    "hw_p $%p parent dip $%p ndevs %d (found)",
43616349Sqs148142 			    hw_p, p_dip, hw_p->ndevs));
43626349Sqs148142 
43636349Sqs148142 			hxgep->hxge_hw_p = NULL;
43646349Sqs148142 			if (hw_p->ndevs) {
43656349Sqs148142 				hw_p->ndevs--;
43666349Sqs148142 			}
43676349Sqs148142 			hw_p->hxge_p = NULL;
43686349Sqs148142 			if (!hw_p->ndevs) {
43696349Sqs148142 				MUTEX_DESTROY(&hw_p->hxge_vlan_lock);
43706349Sqs148142 				MUTEX_DESTROY(&hw_p->hxge_tcam_lock);
43716349Sqs148142 				MUTEX_DESTROY(&hw_p->hxge_cfg_lock);
43726349Sqs148142 				HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43736349Sqs148142 				    "==> hxge_uninit_common_dev: "
43746349Sqs148142 				    "hw_p $%p parent dip $%p ndevs %d (last)",
43756349Sqs148142 				    hw_p, p_dip, hw_p->ndevs));
43766349Sqs148142 
43776349Sqs148142 				if (hw_p == hxge_hw_list) {
43786349Sqs148142 					HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43796349Sqs148142 					    "==> hxge_uninit_common_dev:"
43806349Sqs148142 					    "remove head "
43816349Sqs148142 					    "hw_p $%p parent dip $%p "
43826349Sqs148142 					    "ndevs %d (head)",
43836349Sqs148142 					    hw_p, p_dip, hw_p->ndevs));
43846349Sqs148142 					hxge_hw_list = hw_p->next;
43856349Sqs148142 				} else {
43866349Sqs148142 					HXGE_DEBUG_MSG((hxgep, MOD_CTL,
43876349Sqs148142 					    "==> hxge_uninit_common_dev:"
43886349Sqs148142 					    "remove middle "
43896349Sqs148142 					    "hw_p $%p parent dip $%p "
43906349Sqs148142 					    "ndevs %d (middle)",
43916349Sqs148142 					    hw_p, p_dip, hw_p->ndevs));
43926349Sqs148142 					h_hw_p->next = hw_p->next;
43936349Sqs148142 				}
43946349Sqs148142 
43956349Sqs148142 				KMEM_FREE(hw_p, sizeof (hxge_hw_list_t));
43966349Sqs148142 			}
43976349Sqs148142 			break;
43986349Sqs148142 		} else {
43996349Sqs148142 			h_hw_p = hw_p;
44006349Sqs148142 		}
44016349Sqs148142 	}
44026349Sqs148142 
44036349Sqs148142 	MUTEX_EXIT(&hxge_common_lock);
44046349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MOD_CTL,
44056349Sqs148142 	    "==> hxge_uninit_common_dev (hxge_hw_list) $%p", hxge_hw_list));
44066349Sqs148142 
44076349Sqs148142 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<= hxge_uninit_common_dev"));
44086349Sqs148142 }
44097584SQiyan.Sun@Sun.COM 
44108236SQiyan.Sun@Sun.COM #define	HXGE_MSIX_ENTRIES		32
44118236SQiyan.Sun@Sun.COM #define	HXGE_MSIX_WAIT_COUNT		10
44128236SQiyan.Sun@Sun.COM #define	HXGE_MSIX_PARITY_CHECK_COUNT	30
44138236SQiyan.Sun@Sun.COM 
44147584SQiyan.Sun@Sun.COM static void
hxge_link_poll(void * arg)44157584SQiyan.Sun@Sun.COM hxge_link_poll(void *arg)
44167584SQiyan.Sun@Sun.COM {
44177584SQiyan.Sun@Sun.COM 	p_hxge_t		hxgep = (p_hxge_t)arg;
44187584SQiyan.Sun@Sun.COM 	hpi_handle_t		handle;
44197584SQiyan.Sun@Sun.COM 	cip_link_stat_t		link_stat;
44207584SQiyan.Sun@Sun.COM 	hxge_timeout		*to = &hxgep->timeout;
44217584SQiyan.Sun@Sun.COM 
44227584SQiyan.Sun@Sun.COM 	handle = HXGE_DEV_HPI_HANDLE(hxgep);
44237584SQiyan.Sun@Sun.COM 	HXGE_REG_RD32(handle, CIP_LINK_STAT, &link_stat.value);
44247584SQiyan.Sun@Sun.COM 
44257949SQiyan.Sun@Sun.COM 	if (to->report_link_status ||
44267949SQiyan.Sun@Sun.COM 	    (to->link_status != link_stat.bits.xpcs0_link_up)) {
44277584SQiyan.Sun@Sun.COM 		to->link_status = link_stat.bits.xpcs0_link_up;
44287949SQiyan.Sun@Sun.COM 		to->report_link_status = B_FALSE;
44297584SQiyan.Sun@Sun.COM 
44307584SQiyan.Sun@Sun.COM 		if (link_stat.bits.xpcs0_link_up) {
44317949SQiyan.Sun@Sun.COM 			hxge_link_update(hxgep, LINK_STATE_UP);
44327584SQiyan.Sun@Sun.COM 		} else {
44337949SQiyan.Sun@Sun.COM 			hxge_link_update(hxgep, LINK_STATE_DOWN);
44347584SQiyan.Sun@Sun.COM 		}
44357584SQiyan.Sun@Sun.COM 	}
44367584SQiyan.Sun@Sun.COM 
44377584SQiyan.Sun@Sun.COM 	/* Restart the link status timer to check the link status */
44387584SQiyan.Sun@Sun.COM 	MUTEX_ENTER(&to->lock);
44397584SQiyan.Sun@Sun.COM 	to->id = timeout(hxge_link_poll, arg, to->ticks);
44407584SQiyan.Sun@Sun.COM 	MUTEX_EXIT(&to->lock);
44417584SQiyan.Sun@Sun.COM }
44427949SQiyan.Sun@Sun.COM 
44437949SQiyan.Sun@Sun.COM static void
hxge_link_update(p_hxge_t hxgep,link_state_t state)44447949SQiyan.Sun@Sun.COM hxge_link_update(p_hxge_t hxgep, link_state_t state)
44457949SQiyan.Sun@Sun.COM {
44467949SQiyan.Sun@Sun.COM 	p_hxge_stats_t		statsp = (p_hxge_stats_t)hxgep->statsp;
44477949SQiyan.Sun@Sun.COM 
44487949SQiyan.Sun@Sun.COM 	mac_link_update(hxgep->mach, state);
44497949SQiyan.Sun@Sun.COM 	if (state == LINK_STATE_UP) {
44507949SQiyan.Sun@Sun.COM 		statsp->mac_stats.link_speed = 10000;
44517949SQiyan.Sun@Sun.COM 		statsp->mac_stats.link_duplex = 2;
44527949SQiyan.Sun@Sun.COM 		statsp->mac_stats.link_up = 1;
44537949SQiyan.Sun@Sun.COM 	} else {
44547949SQiyan.Sun@Sun.COM 		statsp->mac_stats.link_speed = 0;
44557949SQiyan.Sun@Sun.COM 		statsp->mac_stats.link_duplex = 0;
44567949SQiyan.Sun@Sun.COM 		statsp->mac_stats.link_up = 0;
44577949SQiyan.Sun@Sun.COM 	}
44587949SQiyan.Sun@Sun.COM }
44598236SQiyan.Sun@Sun.COM 
44608236SQiyan.Sun@Sun.COM static void
hxge_msix_init(p_hxge_t hxgep)44618236SQiyan.Sun@Sun.COM hxge_msix_init(p_hxge_t hxgep)
44628236SQiyan.Sun@Sun.COM {
44638366SQiyan.Sun@Sun.COM 	uint32_t 		data0;
44648366SQiyan.Sun@Sun.COM 	uint32_t 		data1;
44658366SQiyan.Sun@Sun.COM 	uint32_t 		data2;
44668236SQiyan.Sun@Sun.COM 	int			i;
44678366SQiyan.Sun@Sun.COM 	uint32_t		msix_entry0;
44688366SQiyan.Sun@Sun.COM 	uint32_t		msix_entry1;
44698366SQiyan.Sun@Sun.COM 	uint32_t		msix_entry2;
44708366SQiyan.Sun@Sun.COM 	uint32_t		msix_entry3;
44718366SQiyan.Sun@Sun.COM 
44728366SQiyan.Sun@Sun.COM 	/* Change to use MSIx bar instead of indirect access */
44738236SQiyan.Sun@Sun.COM 	for (i = 0; i < HXGE_MSIX_ENTRIES; i++) {
44748366SQiyan.Sun@Sun.COM 		data0 = 0xffffffff - i;
44758366SQiyan.Sun@Sun.COM 		data1 = 0xffffffff - i - 1;
44768366SQiyan.Sun@Sun.COM 		data2 = 0xffffffff - i - 2;
44778366SQiyan.Sun@Sun.COM 
44788366SQiyan.Sun@Sun.COM 		HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16, data0);
44798366SQiyan.Sun@Sun.COM 		HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 4, data1);
44808366SQiyan.Sun@Sun.COM 		HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 8, data2);
448111257SMichael.Speer@Sun.COM 		HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 12, 0);
44828236SQiyan.Sun@Sun.COM 	}
44838236SQiyan.Sun@Sun.COM 
44848366SQiyan.Sun@Sun.COM 	/* Initialize ram data out buffer. */
44858366SQiyan.Sun@Sun.COM 	for (i = 0; i < HXGE_MSIX_ENTRIES; i++) {
44868366SQiyan.Sun@Sun.COM 		HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16, &msix_entry0);
44878366SQiyan.Sun@Sun.COM 		HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 4, &msix_entry1);
44888366SQiyan.Sun@Sun.COM 		HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 8, &msix_entry2);
44898366SQiyan.Sun@Sun.COM 		HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 12, &msix_entry3);
44908366SQiyan.Sun@Sun.COM 	}
44918366SQiyan.Sun@Sun.COM }
44928366SQiyan.Sun@Sun.COM 
44938366SQiyan.Sun@Sun.COM /*
44948366SQiyan.Sun@Sun.COM  * The following function is to support
44958366SQiyan.Sun@Sun.COM  * PSARC/2007/453 MSI-X interrupt limit override.
44968366SQiyan.Sun@Sun.COM  */
44978366SQiyan.Sun@Sun.COM static int
hxge_create_msi_property(p_hxge_t hxgep)44988366SQiyan.Sun@Sun.COM hxge_create_msi_property(p_hxge_t hxgep)
44998236SQiyan.Sun@Sun.COM {
45008366SQiyan.Sun@Sun.COM 	int	nmsi;
45018366SQiyan.Sun@Sun.COM 	extern	int ncpus;
45028366SQiyan.Sun@Sun.COM 
45038366SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==>hxge_create_msi_property"));
45048366SQiyan.Sun@Sun.COM 
45058366SQiyan.Sun@Sun.COM 	(void) ddi_prop_create(DDI_DEV_T_NONE, hxgep->dip,
45068366SQiyan.Sun@Sun.COM 	    DDI_PROP_CANSLEEP, "#msix-request", NULL, 0);
45078366SQiyan.Sun@Sun.COM 	/*
45088366SQiyan.Sun@Sun.COM 	 * The maximum MSI-X requested will be 8.
45098366SQiyan.Sun@Sun.COM 	 * If the # of CPUs is less than 8, we will reqeust
45108366SQiyan.Sun@Sun.COM 	 * # MSI-X based on the # of CPUs.
45118366SQiyan.Sun@Sun.COM 	 */
45128366SQiyan.Sun@Sun.COM 	if (ncpus >= HXGE_MSIX_REQUEST_10G) {
45138366SQiyan.Sun@Sun.COM 		nmsi = HXGE_MSIX_REQUEST_10G;
45148366SQiyan.Sun@Sun.COM 	} else {
45158366SQiyan.Sun@Sun.COM 		nmsi = ncpus;
45168236SQiyan.Sun@Sun.COM 	}
45178236SQiyan.Sun@Sun.COM 
45188366SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, MOD_CTL,
45198366SQiyan.Sun@Sun.COM 	    "==>hxge_create_msi_property(10G): exists 0x%x (nmsi %d)",
45208366SQiyan.Sun@Sun.COM 	    ddi_prop_exists(DDI_DEV_T_NONE, hxgep->dip,
45218366SQiyan.Sun@Sun.COM 	    DDI_PROP_CANSLEEP, "#msix-request"), nmsi));
45228366SQiyan.Sun@Sun.COM 
45238366SQiyan.Sun@Sun.COM 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<==hxge_create_msi_property"));
45248366SQiyan.Sun@Sun.COM 	return (nmsi);
45258236SQiyan.Sun@Sun.COM }
4526