xref: /illumos-gate/usr/src/uts/common/io/hxge/hxge_main.c (revision a512c5d1)
13dec9fcdSqs /*
23dec9fcdSqs  * CDDL HEADER START
33dec9fcdSqs  *
43dec9fcdSqs  * The contents of this file are subject to the terms of the
53dec9fcdSqs  * Common Development and Distribution License (the "License").
63dec9fcdSqs  * You may not use this file except in compliance with the License.
73dec9fcdSqs  *
83dec9fcdSqs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93dec9fcdSqs  * or http://www.opensolaris.org/os/licensing.
103dec9fcdSqs  * See the License for the specific language governing permissions
113dec9fcdSqs  * and limitations under the License.
123dec9fcdSqs  *
133dec9fcdSqs  * When distributing Covered Code, include this CDDL HEADER in each
143dec9fcdSqs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153dec9fcdSqs  * If applicable, add the following below this CDDL HEADER, with the
163dec9fcdSqs  * fields enclosed by brackets "[]" replaced with your own identifying
173dec9fcdSqs  * information: Portions Copyright [yyyy] [name of copyright owner]
183dec9fcdSqs  *
193dec9fcdSqs  * CDDL HEADER END
203dec9fcdSqs  */
213dec9fcdSqs /*
223dec9fcdSqs  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
233dec9fcdSqs  * Use is subject to license terms.
243dec9fcdSqs  */
253dec9fcdSqs 
263dec9fcdSqs /*
273dec9fcdSqs  * SunOs MT STREAMS Hydra 10Gb Ethernet Device Driver.
283dec9fcdSqs  */
293dec9fcdSqs #include <hxge_impl.h>
303dec9fcdSqs #include <hxge_pfc.h>
313dec9fcdSqs 
323dec9fcdSqs /*
333dec9fcdSqs  * PSARC/2007/453 MSI-X interrupt limit override
343dec9fcdSqs  * (This PSARC case is limited to MSI-X vectors
353dec9fcdSqs  *  and SPARC platforms only).
363dec9fcdSqs  */
373dec9fcdSqs #if defined(_BIG_ENDIAN)
383dec9fcdSqs uint32_t hxge_msi_enable = 2;
393dec9fcdSqs #else
403dec9fcdSqs uint32_t hxge_msi_enable = 1;
413dec9fcdSqs #endif
423dec9fcdSqs 
433dec9fcdSqs /*
443dec9fcdSqs  * Globals: tunable parameters (/etc/system or adb)
453dec9fcdSqs  *
463dec9fcdSqs  */
473dec9fcdSqs uint32_t hxge_rbr_size = HXGE_RBR_RBB_DEFAULT;
483dec9fcdSqs uint32_t hxge_rbr_spare_size = 0;
493dec9fcdSqs uint32_t hxge_rcr_size = HXGE_RCR_DEFAULT;
503dec9fcdSqs uint32_t hxge_tx_ring_size = HXGE_TX_RING_DEFAULT;
513dec9fcdSqs uint32_t hxge_bcopy_thresh = TX_BCOPY_MAX;
523dec9fcdSqs uint32_t hxge_dvma_thresh = TX_FASTDVMA_MIN;
533dec9fcdSqs uint32_t hxge_dma_stream_thresh = TX_STREAM_MIN;
54*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint32_t hxge_jumbo_frame_size = MAX_FRAME_SIZE;
553dec9fcdSqs 
563dec9fcdSqs static hxge_os_mutex_t hxgedebuglock;
573dec9fcdSqs static int hxge_debug_init = 0;
583dec9fcdSqs 
593dec9fcdSqs /*
603dec9fcdSqs  * Debugging flags:
613dec9fcdSqs  *		hxge_no_tx_lb : transmit load balancing
623dec9fcdSqs  *		hxge_tx_lb_policy: 0 - TCP/UDP port (default)
633dec9fcdSqs  *				   1 - From the Stack
643dec9fcdSqs  *				   2 - Destination IP Address
653dec9fcdSqs  */
663dec9fcdSqs uint32_t hxge_no_tx_lb = 0;
673dec9fcdSqs uint32_t hxge_tx_lb_policy = HXGE_TX_LB_TCPUDP;
683dec9fcdSqs 
693dec9fcdSqs /*
703dec9fcdSqs  * Add tunable to reduce the amount of time spent in the
713dec9fcdSqs  * ISR doing Rx Processing.
723dec9fcdSqs  */
733dec9fcdSqs uint32_t hxge_max_rx_pkts = 1024;
743dec9fcdSqs 
753dec9fcdSqs /*
763dec9fcdSqs  * Tunables to manage the receive buffer blocks.
773dec9fcdSqs  *
783dec9fcdSqs  * hxge_rx_threshold_hi: copy all buffers.
793dec9fcdSqs  * hxge_rx_bcopy_size_type: receive buffer block size type.
803dec9fcdSqs  * hxge_rx_threshold_lo: copy only up to tunable block size type.
813dec9fcdSqs  */
823dec9fcdSqs hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_6;
833dec9fcdSqs hxge_rxbuf_type_t hxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
843dec9fcdSqs hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_3;
853dec9fcdSqs 
863dec9fcdSqs rtrace_t hpi_rtracebuf;
873dec9fcdSqs 
883dec9fcdSqs /*
893dec9fcdSqs  * Function Prototypes
903dec9fcdSqs  */
913dec9fcdSqs static int hxge_attach(dev_info_t *, ddi_attach_cmd_t);
923dec9fcdSqs static int hxge_detach(dev_info_t *, ddi_detach_cmd_t);
933dec9fcdSqs static void hxge_unattach(p_hxge_t);
943dec9fcdSqs 
953dec9fcdSqs static hxge_status_t hxge_setup_system_dma_pages(p_hxge_t);
963dec9fcdSqs 
973dec9fcdSqs static hxge_status_t hxge_setup_mutexes(p_hxge_t);
983dec9fcdSqs static void hxge_destroy_mutexes(p_hxge_t);
993dec9fcdSqs 
1003dec9fcdSqs static hxge_status_t hxge_map_regs(p_hxge_t hxgep);
1013dec9fcdSqs static void hxge_unmap_regs(p_hxge_t hxgep);
1023dec9fcdSqs 
1033dec9fcdSqs hxge_status_t hxge_add_intrs(p_hxge_t hxgep);
1043dec9fcdSqs static hxge_status_t hxge_add_soft_intrs(p_hxge_t hxgep);
1053dec9fcdSqs static void hxge_remove_intrs(p_hxge_t hxgep);
1063dec9fcdSqs static void hxge_remove_soft_intrs(p_hxge_t hxgep);
1073dec9fcdSqs static hxge_status_t hxge_add_intrs_adv(p_hxge_t hxgep);
1083dec9fcdSqs static hxge_status_t hxge_add_intrs_adv_type(p_hxge_t, uint32_t);
1093dec9fcdSqs static hxge_status_t hxge_add_intrs_adv_type_fix(p_hxge_t, uint32_t);
1103dec9fcdSqs void hxge_intrs_enable(p_hxge_t hxgep);
1113dec9fcdSqs static void hxge_intrs_disable(p_hxge_t hxgep);
1123dec9fcdSqs static void hxge_suspend(p_hxge_t);
1133dec9fcdSqs static hxge_status_t hxge_resume(p_hxge_t);
1143dec9fcdSqs hxge_status_t hxge_setup_dev(p_hxge_t);
1153dec9fcdSqs static void hxge_destroy_dev(p_hxge_t);
1163dec9fcdSqs hxge_status_t hxge_alloc_mem_pool(p_hxge_t);
1173dec9fcdSqs static void hxge_free_mem_pool(p_hxge_t);
1183dec9fcdSqs static hxge_status_t hxge_alloc_rx_mem_pool(p_hxge_t);
1193dec9fcdSqs static void hxge_free_rx_mem_pool(p_hxge_t);
1203dec9fcdSqs static hxge_status_t hxge_alloc_tx_mem_pool(p_hxge_t);
1213dec9fcdSqs static void hxge_free_tx_mem_pool(p_hxge_t);
1223dec9fcdSqs static hxge_status_t hxge_dma_mem_alloc(p_hxge_t, dma_method_t,
1233dec9fcdSqs     struct ddi_dma_attr *, size_t, ddi_device_acc_attr_t *, uint_t,
1243dec9fcdSqs     p_hxge_dma_common_t);
1253dec9fcdSqs static void hxge_dma_mem_free(p_hxge_dma_common_t);
1263dec9fcdSqs static hxge_status_t hxge_alloc_rx_buf_dma(p_hxge_t, uint16_t,
1273dec9fcdSqs     p_hxge_dma_common_t *, size_t, size_t, uint32_t *);
1283dec9fcdSqs static void hxge_free_rx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t);
1293dec9fcdSqs static hxge_status_t hxge_alloc_rx_cntl_dma(p_hxge_t, uint16_t,
1303dec9fcdSqs     p_hxge_dma_common_t *, size_t);
1313dec9fcdSqs static void hxge_free_rx_cntl_dma(p_hxge_t, p_hxge_dma_common_t);
1323dec9fcdSqs static hxge_status_t hxge_alloc_tx_buf_dma(p_hxge_t, uint16_t,
1333dec9fcdSqs     p_hxge_dma_common_t *, size_t, size_t, uint32_t *);
1343dec9fcdSqs static void hxge_free_tx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t);
1353dec9fcdSqs static hxge_status_t hxge_alloc_tx_cntl_dma(p_hxge_t, uint16_t,
1363dec9fcdSqs     p_hxge_dma_common_t *, size_t);
1373dec9fcdSqs static void hxge_free_tx_cntl_dma(p_hxge_t, p_hxge_dma_common_t);
1383dec9fcdSqs static int hxge_init_common_dev(p_hxge_t);
1393dec9fcdSqs static void hxge_uninit_common_dev(p_hxge_t);
1403dec9fcdSqs 
1413dec9fcdSqs /*
1423dec9fcdSqs  * The next declarations are for the GLDv3 interface.
1433dec9fcdSqs  */
1443dec9fcdSqs static int hxge_m_start(void *);
1453dec9fcdSqs static void hxge_m_stop(void *);
1463dec9fcdSqs static int hxge_m_unicst(void *, const uint8_t *);
1473dec9fcdSqs static int hxge_m_multicst(void *, boolean_t, const uint8_t *);
1483dec9fcdSqs static int hxge_m_promisc(void *, boolean_t);
1493dec9fcdSqs static void hxge_m_ioctl(void *, queue_t *, mblk_t *);
1503dec9fcdSqs static void hxge_m_resources(void *);
1513dec9fcdSqs static hxge_status_t hxge_mac_register(p_hxge_t hxgep);
1523dec9fcdSqs 
1533dec9fcdSqs static int hxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr);
1543dec9fcdSqs static int hxge_m_mmac_remove(void *arg, mac_addr_slot_t slot);
1553dec9fcdSqs static int hxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr);
1563dec9fcdSqs static int hxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr);
1573dec9fcdSqs static boolean_t hxge_m_getcapab(void *, mac_capab_t, void *);
158*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static boolean_t hxge_param_locked(mac_prop_id_t pr_num);
159*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
160*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States     uint_t pr_valsize, const void *pr_val);
161*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
162*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States     uint_t pr_flags, uint_t pr_valsize, void *pr_val);
163*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int hxge_get_def_val(hxge_t *hxgep, mac_prop_id_t pr_num,
164*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States     uint_t pr_valsize, void *pr_val);
165*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name,
166*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States     uint_t pr_valsize, const void *pr_val);
167*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name,
168*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States     uint_t pr_flags, uint_t pr_valsize, void *pr_val);
169*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static void hxge_link_poll(void *arg);
170*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
171*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States mac_priv_prop_t hxge_priv_props[] = {
172*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	{"_rxdma_intr_time", MAC_PROP_PERM_RW},
173*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	{"_rxdma_intr_pkts", MAC_PROP_PERM_RW},
174*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	{"_class_opt_ipv4_tcp", MAC_PROP_PERM_RW},
175*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	{"_class_opt_ipv4_udp", MAC_PROP_PERM_RW},
176*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	{"_class_opt_ipv4_ah", MAC_PROP_PERM_RW},
177*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	{"_class_opt_ipv4_sctp", MAC_PROP_PERM_RW},
178*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	{"_class_opt_ipv6_tcp", MAC_PROP_PERM_RW},
179*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	{"_class_opt_ipv6_udp", MAC_PROP_PERM_RW},
180*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	{"_class_opt_ipv6_ah", MAC_PROP_PERM_RW},
181*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	{"_class_opt_ipv6_sctp", MAC_PROP_PERM_RW}
182*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States };
183*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
184*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States #define	HXGE_MAX_PRIV_PROPS	\
185*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	(sizeof (hxge_priv_props)/sizeof (mac_priv_prop_t))
1863dec9fcdSqs 
1873dec9fcdSqs #define	HXGE_MAGIC	0x4E584745UL
1883dec9fcdSqs #define	MAX_DUMP_SZ 256
1893dec9fcdSqs 
190*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States #define	HXGE_M_CALLBACK_FLAGS	\
191*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	(MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP)
1923dec9fcdSqs 
1933dec9fcdSqs extern mblk_t *hxge_m_tx(void *arg, mblk_t *mp);
1943dec9fcdSqs extern hxge_status_t hxge_pfc_set_default_mac_addr(p_hxge_t hxgep);
1953dec9fcdSqs 
1963dec9fcdSqs static mac_callbacks_t hxge_m_callbacks = {
1973dec9fcdSqs 	HXGE_M_CALLBACK_FLAGS,
1983dec9fcdSqs 	hxge_m_stat,
1993dec9fcdSqs 	hxge_m_start,
2003dec9fcdSqs 	hxge_m_stop,
2013dec9fcdSqs 	hxge_m_promisc,
2023dec9fcdSqs 	hxge_m_multicst,
2033dec9fcdSqs 	hxge_m_unicst,
2043dec9fcdSqs 	hxge_m_tx,
2053dec9fcdSqs 	hxge_m_resources,
2063dec9fcdSqs 	hxge_m_ioctl,
207*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxge_m_getcapab,
208*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	NULL,
209*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	NULL,
210*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxge_m_setprop,
211*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxge_m_getprop
2123dec9fcdSqs };
2133dec9fcdSqs 
2143dec9fcdSqs /* Enable debug messages as necessary. */
215*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint64_t hxge_debug_level = 0;
2163dec9fcdSqs 
2173dec9fcdSqs /*
2183dec9fcdSqs  * This list contains the instance structures for the Hydra
2193dec9fcdSqs  * devices present in the system. The lock exists to guarantee
2203dec9fcdSqs  * mutually exclusive access to the list.
2213dec9fcdSqs  */
2223dec9fcdSqs void *hxge_list = NULL;
2233dec9fcdSqs void *hxge_hw_list = NULL;
2243dec9fcdSqs hxge_os_mutex_t hxge_common_lock;
2253dec9fcdSqs 
2263dec9fcdSqs extern uint64_t hpi_debug_level;
2273dec9fcdSqs 
2283dec9fcdSqs extern hxge_status_t hxge_ldgv_init();
2293dec9fcdSqs extern hxge_status_t hxge_ldgv_uninit();
2303dec9fcdSqs extern hxge_status_t hxge_intr_ldgv_init();
2313dec9fcdSqs extern void hxge_fm_init(p_hxge_t hxgep, ddi_device_acc_attr_t *reg_attr,
2323dec9fcdSqs     ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr);
2333dec9fcdSqs extern void hxge_fm_fini(p_hxge_t hxgep);
2343dec9fcdSqs 
2353dec9fcdSqs /*
2363dec9fcdSqs  * Count used to maintain the number of buffers being used
2373dec9fcdSqs  * by Hydra instances and loaned up to the upper layers.
2383dec9fcdSqs  */
2393dec9fcdSqs uint32_t hxge_mblks_pending = 0;
2403dec9fcdSqs 
2413dec9fcdSqs /*
2423dec9fcdSqs  * Device register access attributes for PIO.
2433dec9fcdSqs  */
2443dec9fcdSqs static ddi_device_acc_attr_t hxge_dev_reg_acc_attr = {
2453dec9fcdSqs 	DDI_DEVICE_ATTR_V0,
2463dec9fcdSqs 	DDI_STRUCTURE_LE_ACC,
2473dec9fcdSqs 	DDI_STRICTORDER_ACC,
2483dec9fcdSqs };
2493dec9fcdSqs 
2503dec9fcdSqs /*
2513dec9fcdSqs  * Device descriptor access attributes for DMA.
2523dec9fcdSqs  */
2533dec9fcdSqs static ddi_device_acc_attr_t hxge_dev_desc_dma_acc_attr = {
2543dec9fcdSqs 	DDI_DEVICE_ATTR_V0,
2553dec9fcdSqs 	DDI_STRUCTURE_LE_ACC,
2563dec9fcdSqs 	DDI_STRICTORDER_ACC
2573dec9fcdSqs };
2583dec9fcdSqs 
2593dec9fcdSqs /*
2603dec9fcdSqs  * Device buffer access attributes for DMA.
2613dec9fcdSqs  */
2623dec9fcdSqs static ddi_device_acc_attr_t hxge_dev_buf_dma_acc_attr = {
2633dec9fcdSqs 	DDI_DEVICE_ATTR_V0,
2643dec9fcdSqs 	DDI_STRUCTURE_BE_ACC,
2653dec9fcdSqs 	DDI_STRICTORDER_ACC
2663dec9fcdSqs };
2673dec9fcdSqs 
2683dec9fcdSqs ddi_dma_attr_t hxge_desc_dma_attr = {
2693dec9fcdSqs 	DMA_ATTR_V0,		/* version number. */
2703dec9fcdSqs 	0,			/* low address */
2713dec9fcdSqs 	0xffffffffffffffff,	/* high address */
2723dec9fcdSqs 	0xffffffffffffffff,	/* address counter max */
2733dec9fcdSqs 	0x100000,		/* alignment */
2743dec9fcdSqs 	0xfc00fc,		/* dlim_burstsizes */
2753dec9fcdSqs 	0x1,			/* minimum transfer size */
2763dec9fcdSqs 	0xffffffffffffffff,	/* maximum transfer size */
2773dec9fcdSqs 	0xffffffffffffffff,	/* maximum segment size */
2783dec9fcdSqs 	1,			/* scatter/gather list length */
2793dec9fcdSqs 	(unsigned int)1,	/* granularity */
2803dec9fcdSqs 	0			/* attribute flags */
2813dec9fcdSqs };
2823dec9fcdSqs 
2833dec9fcdSqs ddi_dma_attr_t hxge_tx_dma_attr = {
2843dec9fcdSqs 	DMA_ATTR_V0,		/* version number. */
2853dec9fcdSqs 	0,			/* low address */
2863dec9fcdSqs 	0xffffffffffffffff,	/* high address */
2873dec9fcdSqs 	0xffffffffffffffff,	/* address counter max */
2883dec9fcdSqs #if defined(_BIG_ENDIAN)
2893dec9fcdSqs 	0x2000,			/* alignment */
2903dec9fcdSqs #else
2913dec9fcdSqs 	0x1000,			/* alignment */
2923dec9fcdSqs #endif
2933dec9fcdSqs 	0xfc00fc,		/* dlim_burstsizes */
2943dec9fcdSqs 	0x1,			/* minimum transfer size */
2953dec9fcdSqs 	0xffffffffffffffff,	/* maximum transfer size */
2963dec9fcdSqs 	0xffffffffffffffff,	/* maximum segment size */
2973dec9fcdSqs 	5,			/* scatter/gather list length */
2983dec9fcdSqs 	(unsigned int)1,	/* granularity */
2993dec9fcdSqs 	0			/* attribute flags */
3003dec9fcdSqs };
3013dec9fcdSqs 
3023dec9fcdSqs ddi_dma_attr_t hxge_rx_dma_attr = {
3033dec9fcdSqs 	DMA_ATTR_V0,		/* version number. */
3043dec9fcdSqs 	0,			/* low address */
3053dec9fcdSqs 	0xffffffffffffffff,	/* high address */
3063dec9fcdSqs 	0xffffffffffffffff,	/* address counter max */
3073dec9fcdSqs 	0x10000,		/* alignment */
3083dec9fcdSqs 	0xfc00fc,		/* dlim_burstsizes */
3093dec9fcdSqs 	0x1,			/* minimum transfer size */
3103dec9fcdSqs 	0xffffffffffffffff,	/* maximum transfer size */
3113dec9fcdSqs 	0xffffffffffffffff,	/* maximum segment size */
3123dec9fcdSqs 	1,			/* scatter/gather list length */
3133dec9fcdSqs 	(unsigned int)1,	/* granularity */
3143dec9fcdSqs 	DDI_DMA_RELAXED_ORDERING /* attribute flags */
3153dec9fcdSqs };
3163dec9fcdSqs 
3173dec9fcdSqs ddi_dma_lim_t hxge_dma_limits = {
3183dec9fcdSqs 	(uint_t)0,		/* dlim_addr_lo */
3193dec9fcdSqs 	(uint_t)0xffffffff,	/* dlim_addr_hi */
3203dec9fcdSqs 	(uint_t)0xffffffff,	/* dlim_cntr_max */
3213dec9fcdSqs 	(uint_t)0xfc00fc,	/* dlim_burstsizes for 32 and 64 bit xfers */
3223dec9fcdSqs 	0x1,			/* dlim_minxfer */
3233dec9fcdSqs 	1024			/* dlim_speed */
3243dec9fcdSqs };
3253dec9fcdSqs 
3263dec9fcdSqs dma_method_t hxge_force_dma = DVMA;
3273dec9fcdSqs 
3283dec9fcdSqs /*
3293dec9fcdSqs  * dma chunk sizes.
3303dec9fcdSqs  *
3313dec9fcdSqs  * Try to allocate the largest possible size
3323dec9fcdSqs  * so that fewer number of dma chunks would be managed
3333dec9fcdSqs  */
3343dec9fcdSqs size_t alloc_sizes[] = {
3353dec9fcdSqs     0x1000, 0x2000, 0x4000, 0x8000,
3363dec9fcdSqs     0x10000, 0x20000, 0x40000, 0x80000,
3373dec9fcdSqs     0x100000, 0x200000, 0x400000, 0x800000, 0x1000000
3383dec9fcdSqs };
3393dec9fcdSqs 
3403dec9fcdSqs /*
3413dec9fcdSqs  * Translate "dev_t" to a pointer to the associated "dev_info_t".
3423dec9fcdSqs  */
3433dec9fcdSqs static int
3443dec9fcdSqs hxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
3453dec9fcdSqs {
3463dec9fcdSqs 	p_hxge_t	hxgep = NULL;
3473dec9fcdSqs 	int		instance;
3483dec9fcdSqs 	int		status = DDI_SUCCESS;
3493dec9fcdSqs 
3503dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_attach"));
3513dec9fcdSqs 
3523dec9fcdSqs 	/*
3533dec9fcdSqs 	 * Get the device instance since we'll need to setup or retrieve a soft
3543dec9fcdSqs 	 * state for this instance.
3553dec9fcdSqs 	 */
3563dec9fcdSqs 	instance = ddi_get_instance(dip);
3573dec9fcdSqs 
3583dec9fcdSqs 	switch (cmd) {
3593dec9fcdSqs 	case DDI_ATTACH:
3603dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_ATTACH"));
3613dec9fcdSqs 		break;
3623dec9fcdSqs 
3633dec9fcdSqs 	case DDI_RESUME:
3643dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_RESUME"));
3653dec9fcdSqs 		hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance);
3663dec9fcdSqs 		if (hxgep == NULL) {
3673dec9fcdSqs 			status = DDI_FAILURE;
3683dec9fcdSqs 			break;
3693dec9fcdSqs 		}
3703dec9fcdSqs 		if (hxgep->dip != dip) {
3713dec9fcdSqs 			status = DDI_FAILURE;
3723dec9fcdSqs 			break;
3733dec9fcdSqs 		}
3743dec9fcdSqs 		if (hxgep->suspended == DDI_PM_SUSPEND) {
3753dec9fcdSqs 			status = ddi_dev_is_needed(hxgep->dip, 0, 1);
3763dec9fcdSqs 		} else {
3773dec9fcdSqs 			(void) hxge_resume(hxgep);
3783dec9fcdSqs 		}
3793dec9fcdSqs 		goto hxge_attach_exit;
3803dec9fcdSqs 
3813dec9fcdSqs 	case DDI_PM_RESUME:
3823dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_RESUME"));
3833dec9fcdSqs 		hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance);
3843dec9fcdSqs 		if (hxgep == NULL) {
3853dec9fcdSqs 			status = DDI_FAILURE;
3863dec9fcdSqs 			break;
3873dec9fcdSqs 		}
3883dec9fcdSqs 		if (hxgep->dip != dip) {
3893dec9fcdSqs 			status = DDI_FAILURE;
3903dec9fcdSqs 			break;
3913dec9fcdSqs 		}
3923dec9fcdSqs 		(void) hxge_resume(hxgep);
3933dec9fcdSqs 		goto hxge_attach_exit;
3943dec9fcdSqs 
3953dec9fcdSqs 	default:
3963dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing unknown"));
3973dec9fcdSqs 		status = DDI_FAILURE;
3983dec9fcdSqs 		goto hxge_attach_exit;
3993dec9fcdSqs 	}
4003dec9fcdSqs 
4013dec9fcdSqs 	if (ddi_soft_state_zalloc(hxge_list, instance) == DDI_FAILURE) {
4023dec9fcdSqs 		status = DDI_FAILURE;
4033dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, DDI_CTL,
4043dec9fcdSqs 		    "ddi_soft_state_zalloc failed"));
4053dec9fcdSqs 		goto hxge_attach_exit;
4063dec9fcdSqs 	}
4073dec9fcdSqs 
4083dec9fcdSqs 	hxgep = ddi_get_soft_state(hxge_list, instance);
4093dec9fcdSqs 	if (hxgep == NULL) {
4103dec9fcdSqs 		status = HXGE_ERROR;
4113dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, DDI_CTL,
4123dec9fcdSqs 		    "ddi_get_soft_state failed"));
4133dec9fcdSqs 		goto hxge_attach_fail2;
4143dec9fcdSqs 	}
4153dec9fcdSqs 
4163dec9fcdSqs 	hxgep->drv_state = 0;
4173dec9fcdSqs 	hxgep->dip = dip;
4183dec9fcdSqs 	hxgep->instance = instance;
4193dec9fcdSqs 	hxgep->p_dip = ddi_get_parent(dip);
4203dec9fcdSqs 	hxgep->hxge_debug_level = hxge_debug_level;
4213dec9fcdSqs 	hpi_debug_level = hxge_debug_level;
4223dec9fcdSqs 
4233dec9fcdSqs 	hxge_fm_init(hxgep, &hxge_dev_reg_acc_attr, &hxge_dev_desc_dma_acc_attr,
4243dec9fcdSqs 	    &hxge_rx_dma_attr);
4253dec9fcdSqs 
4263dec9fcdSqs 	status = hxge_map_regs(hxgep);
4273dec9fcdSqs 	if (status != HXGE_OK) {
4283dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_map_regs failed"));
4293dec9fcdSqs 		goto hxge_attach_fail3;
4303dec9fcdSqs 	}
4313dec9fcdSqs 
4323dec9fcdSqs 	status = hxge_init_common_dev(hxgep);
4333dec9fcdSqs 	if (status != HXGE_OK) {
4343dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4353dec9fcdSqs 		    "hxge_init_common_dev failed"));
4363dec9fcdSqs 		goto hxge_attach_fail4;
4373dec9fcdSqs 	}
4383dec9fcdSqs 
4393dec9fcdSqs 	/*
4403dec9fcdSqs 	 * Setup the Ndd parameters for this instance.
4413dec9fcdSqs 	 */
4423dec9fcdSqs 	hxge_init_param(hxgep);
4433dec9fcdSqs 
4443dec9fcdSqs 	/*
4453dec9fcdSqs 	 * Setup Register Tracing Buffer.
4463dec9fcdSqs 	 */
4473dec9fcdSqs 	hpi_rtrace_buf_init((rtrace_t *)&hpi_rtracebuf);
4483dec9fcdSqs 
4493dec9fcdSqs 	/* init stats ptr */
4503dec9fcdSqs 	hxge_init_statsp(hxgep);
4513dec9fcdSqs 
452*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	status = hxge_setup_mutexes(hxgep);
453*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if (status != HXGE_OK) {
454*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set mutex failed"));
455*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		goto hxge_attach_fail;
456*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
457*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
4583dec9fcdSqs 	status = hxge_get_config_properties(hxgep);
4593dec9fcdSqs 	if (status != HXGE_OK) {
4603dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "get_hw create failed"));
4613dec9fcdSqs 		goto hxge_attach_fail;
4623dec9fcdSqs 	}
4633dec9fcdSqs 
4643dec9fcdSqs 	/*
4653dec9fcdSqs 	 * Setup the Kstats for the driver.
4663dec9fcdSqs 	 */
4673dec9fcdSqs 	hxge_setup_kstats(hxgep);
4683dec9fcdSqs 	hxge_setup_param(hxgep);
4693dec9fcdSqs 
4703dec9fcdSqs 	status = hxge_setup_system_dma_pages(hxgep);
4713dec9fcdSqs 	if (status != HXGE_OK) {
4723dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "set dma page failed"));
4733dec9fcdSqs 		goto hxge_attach_fail;
4743dec9fcdSqs 	}
4753dec9fcdSqs 
4763dec9fcdSqs 	hxge_hw_id_init(hxgep);
4773dec9fcdSqs 	hxge_hw_init_niu_common(hxgep);
4783dec9fcdSqs 
4793dec9fcdSqs 	status = hxge_setup_dev(hxgep);
4803dec9fcdSqs 	if (status != DDI_SUCCESS) {
4813dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set dev failed"));
4823dec9fcdSqs 		goto hxge_attach_fail;
4833dec9fcdSqs 	}
4843dec9fcdSqs 
4853dec9fcdSqs 	status = hxge_add_intrs(hxgep);
4863dec9fcdSqs 	if (status != DDI_SUCCESS) {
4873dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "add_intr failed"));
4883dec9fcdSqs 		goto hxge_attach_fail;
4893dec9fcdSqs 	}
4903dec9fcdSqs 
4913dec9fcdSqs 	status = hxge_add_soft_intrs(hxgep);
4923dec9fcdSqs 	if (status != DDI_SUCCESS) {
4933dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, HXGE_ERR_CTL, "add_soft_intr failed"));
4943dec9fcdSqs 		goto hxge_attach_fail;
4953dec9fcdSqs 	}
4963dec9fcdSqs 
4973dec9fcdSqs 	/*
4983dec9fcdSqs 	 * Enable interrupts.
4993dec9fcdSqs 	 */
5003dec9fcdSqs 	hxge_intrs_enable(hxgep);
5013dec9fcdSqs 
5023dec9fcdSqs 	if ((status = hxge_mac_register(hxgep)) != HXGE_OK) {
5033dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL,
5043dec9fcdSqs 		    "unable to register to mac layer (%d)", status));
5053dec9fcdSqs 		goto hxge_attach_fail;
5063dec9fcdSqs 	}
507*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	mac_link_update(hxgep->mach, LINK_STATE_UNKNOWN);
508*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxgep->timeout.link_status = 0;
509*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxgep->timeout.ticks = drv_usectohz(2 * 1000000);
510*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
511*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	/* Start the link status timer to check the link status */
512*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_ENTER(&hxgep->timeout.lock);
513*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep,
514*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	    hxgep->timeout.ticks);
515*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_EXIT(&hxgep->timeout.lock);
5163dec9fcdSqs 
5173dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "registered to mac (instance %d)",
5183dec9fcdSqs 	    instance));
5193dec9fcdSqs 
5203dec9fcdSqs 	goto hxge_attach_exit;
5213dec9fcdSqs 
5223dec9fcdSqs hxge_attach_fail:
5233dec9fcdSqs 	hxge_unattach(hxgep);
5243dec9fcdSqs 	goto hxge_attach_fail1;
5253dec9fcdSqs 
5263dec9fcdSqs hxge_attach_fail5:
5273dec9fcdSqs 	/*
5283dec9fcdSqs 	 * Tear down the ndd parameters setup.
5293dec9fcdSqs 	 */
5303dec9fcdSqs 	hxge_destroy_param(hxgep);
5313dec9fcdSqs 
5323dec9fcdSqs 	/*
5333dec9fcdSqs 	 * Tear down the kstat setup.
5343dec9fcdSqs 	 */
5353dec9fcdSqs 	hxge_destroy_kstats(hxgep);
5363dec9fcdSqs 
5373dec9fcdSqs hxge_attach_fail4:
5383dec9fcdSqs 	if (hxgep->hxge_hw_p) {
5393dec9fcdSqs 		hxge_uninit_common_dev(hxgep);
5403dec9fcdSqs 		hxgep->hxge_hw_p = NULL;
5413dec9fcdSqs 	}
5423dec9fcdSqs hxge_attach_fail3:
5433dec9fcdSqs 	/*
5443dec9fcdSqs 	 * Unmap the register setup.
5453dec9fcdSqs 	 */
5463dec9fcdSqs 	hxge_unmap_regs(hxgep);
5473dec9fcdSqs 
5483dec9fcdSqs 	hxge_fm_fini(hxgep);
5493dec9fcdSqs 
5503dec9fcdSqs hxge_attach_fail2:
5513dec9fcdSqs 	ddi_soft_state_free(hxge_list, hxgep->instance);
5523dec9fcdSqs 
5533dec9fcdSqs hxge_attach_fail1:
5543dec9fcdSqs 	if (status != HXGE_OK)
5553dec9fcdSqs 		status = (HXGE_ERROR | HXGE_DDI_FAILED);
5563dec9fcdSqs 	hxgep = NULL;
5573dec9fcdSqs 
5583dec9fcdSqs hxge_attach_exit:
5593dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_attach status = 0x%08x",
5603dec9fcdSqs 	    status));
5613dec9fcdSqs 
5623dec9fcdSqs 	return (status);
5633dec9fcdSqs }
5643dec9fcdSqs 
5653dec9fcdSqs static int
5663dec9fcdSqs hxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
5673dec9fcdSqs {
5683dec9fcdSqs 	int		status = DDI_SUCCESS;
5693dec9fcdSqs 	int		instance;
5703dec9fcdSqs 	p_hxge_t	hxgep = NULL;
5713dec9fcdSqs 
5723dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_detach"));
5733dec9fcdSqs 	instance = ddi_get_instance(dip);
5743dec9fcdSqs 	hxgep = ddi_get_soft_state(hxge_list, instance);
5753dec9fcdSqs 	if (hxgep == NULL) {
5763dec9fcdSqs 		status = DDI_FAILURE;
5773dec9fcdSqs 		goto hxge_detach_exit;
5783dec9fcdSqs 	}
5793dec9fcdSqs 
5803dec9fcdSqs 	switch (cmd) {
5813dec9fcdSqs 	case DDI_DETACH:
5823dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_DETACH"));
5833dec9fcdSqs 		break;
5843dec9fcdSqs 
5853dec9fcdSqs 	case DDI_PM_SUSPEND:
5863dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
5873dec9fcdSqs 		hxgep->suspended = DDI_PM_SUSPEND;
5883dec9fcdSqs 		hxge_suspend(hxgep);
5893dec9fcdSqs 		break;
5903dec9fcdSqs 
5913dec9fcdSqs 	case DDI_SUSPEND:
5923dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_SUSPEND"));
5933dec9fcdSqs 		if (hxgep->suspended != DDI_PM_SUSPEND) {
5943dec9fcdSqs 			hxgep->suspended = DDI_SUSPEND;
5953dec9fcdSqs 			hxge_suspend(hxgep);
5963dec9fcdSqs 		}
5973dec9fcdSqs 		break;
5983dec9fcdSqs 
5993dec9fcdSqs 	default:
6003dec9fcdSqs 		status = DDI_FAILURE;
6013dec9fcdSqs 		break;
6023dec9fcdSqs 	}
6033dec9fcdSqs 
6043dec9fcdSqs 	if (cmd != DDI_DETACH)
6053dec9fcdSqs 		goto hxge_detach_exit;
6063dec9fcdSqs 
6073dec9fcdSqs 	/*
6083dec9fcdSqs 	 * Stop the xcvr polling.
6093dec9fcdSqs 	 */
6103dec9fcdSqs 	hxgep->suspended = cmd;
6113dec9fcdSqs 
612*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	/* Stop the link status timer before unregistering */
613*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_ENTER(&hxgep->timeout.lock);
614*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if (hxgep->timeout.id)
615*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		(void) untimeout(hxgep->timeout.id);
616*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_EXIT(&hxgep->timeout.lock);
617*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
6183dec9fcdSqs 	if (hxgep->mach && (status = mac_unregister(hxgep->mach)) != 0) {
6193dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
6203dec9fcdSqs 		    "<== hxge_detach status = 0x%08X", status));
6213dec9fcdSqs 		return (DDI_FAILURE);
6223dec9fcdSqs 	}
6233dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
6243dec9fcdSqs 	    "<== hxge_detach (mac_unregister) status = 0x%08X", status));
6253dec9fcdSqs 
6263dec9fcdSqs 	hxge_unattach(hxgep);
6273dec9fcdSqs 	hxgep = NULL;
6283dec9fcdSqs 
6293dec9fcdSqs hxge_detach_exit:
6303dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_detach status = 0x%08X",
6313dec9fcdSqs 	    status));
6323dec9fcdSqs 
6333dec9fcdSqs 	return (status);
6343dec9fcdSqs }
6353dec9fcdSqs 
6363dec9fcdSqs static void
6373dec9fcdSqs hxge_unattach(p_hxge_t hxgep)
6383dec9fcdSqs {
6393dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unattach"));
6403dec9fcdSqs 
6413dec9fcdSqs 	if (hxgep == NULL || hxgep->dev_regs == NULL) {
6423dec9fcdSqs 		return;
6433dec9fcdSqs 	}
6443dec9fcdSqs 
6453dec9fcdSqs 	if (hxgep->hxge_hw_p) {
6463dec9fcdSqs 		hxge_uninit_common_dev(hxgep);
6473dec9fcdSqs 		hxgep->hxge_hw_p = NULL;
6483dec9fcdSqs 	}
6493dec9fcdSqs 
6503dec9fcdSqs 	if (hxgep->hxge_timerid) {
6513dec9fcdSqs 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
6523dec9fcdSqs 		hxgep->hxge_timerid = 0;
6533dec9fcdSqs 	}
6543dec9fcdSqs 
6553dec9fcdSqs 	/* Stop any further interrupts. */
6563dec9fcdSqs 	hxge_remove_intrs(hxgep);
6573dec9fcdSqs 
6583dec9fcdSqs 	/* Remove soft interrups */
6593dec9fcdSqs 	hxge_remove_soft_intrs(hxgep);
6603dec9fcdSqs 
6613dec9fcdSqs 	/* Stop the device and free resources. */
6623dec9fcdSqs 	hxge_destroy_dev(hxgep);
6633dec9fcdSqs 
6643dec9fcdSqs 	/* Tear down the ndd parameters setup. */
6653dec9fcdSqs 	hxge_destroy_param(hxgep);
6663dec9fcdSqs 
6673dec9fcdSqs 	/* Tear down the kstat setup. */
6683dec9fcdSqs 	hxge_destroy_kstats(hxgep);
6693dec9fcdSqs 
6703dec9fcdSqs 	/*
6713dec9fcdSqs 	 * Remove the list of ndd parameters which were setup during attach.
6723dec9fcdSqs 	 */
6733dec9fcdSqs 	if (hxgep->dip) {
6743dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, OBP_CTL,
6753dec9fcdSqs 		    " hxge_unattach: remove all properties"));
6763dec9fcdSqs 		(void) ddi_prop_remove_all(hxgep->dip);
6773dec9fcdSqs 	}
6783dec9fcdSqs 
679fe930412Sqs 	/*
680fe930412Sqs 	 * Reset RDC, TDC, PFC, and VMAC blocks from PEU to clear any
681fe930412Sqs 	 * previous state before unmapping the registers.
682fe930412Sqs 	 */
683fe930412Sqs 	HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, 0x0000001E);
684fe930412Sqs 	HXGE_DELAY(1000);
685fe930412Sqs 
6863dec9fcdSqs 	/*
6873dec9fcdSqs 	 * Unmap the register setup.
6883dec9fcdSqs 	 */
6893dec9fcdSqs 	hxge_unmap_regs(hxgep);
6903dec9fcdSqs 
6913dec9fcdSqs 	hxge_fm_fini(hxgep);
6923dec9fcdSqs 
693*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	/* Destroy all mutexes.  */
694*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxge_destroy_mutexes(hxgep);
695*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
6963dec9fcdSqs 	/*
6973dec9fcdSqs 	 * Free the soft state data structures allocated with this instance.
6983dec9fcdSqs 	 */
6993dec9fcdSqs 	ddi_soft_state_free(hxge_list, hxgep->instance);
7003dec9fcdSqs 
7013dec9fcdSqs 	HXGE_DEBUG_MSG((NULL, DDI_CTL, "<== hxge_unattach"));
7023dec9fcdSqs }
7033dec9fcdSqs 
7043dec9fcdSqs static hxge_status_t
7053dec9fcdSqs hxge_map_regs(p_hxge_t hxgep)
7063dec9fcdSqs {
7073dec9fcdSqs 	int		ddi_status = DDI_SUCCESS;
7083dec9fcdSqs 	p_dev_regs_t	dev_regs;
7093dec9fcdSqs 
7103dec9fcdSqs #ifdef	HXGE_DEBUG
7113dec9fcdSqs 	char		*sysname;
7123dec9fcdSqs #endif
7133dec9fcdSqs 
7143dec9fcdSqs 	off_t		regsize;
7153dec9fcdSqs 	hxge_status_t	status = HXGE_OK;
7163dec9fcdSqs 	int		nregs;
7173dec9fcdSqs 
7183dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_map_regs"));
7193dec9fcdSqs 
7203dec9fcdSqs 	if (ddi_dev_nregs(hxgep->dip, &nregs) != DDI_SUCCESS)
7213dec9fcdSqs 		return (HXGE_ERROR);
7223dec9fcdSqs 
7233dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_regs: nregs: %d", nregs));
7243dec9fcdSqs 
7253dec9fcdSqs 	hxgep->dev_regs = NULL;
7263dec9fcdSqs 	dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
7273dec9fcdSqs 	dev_regs->hxge_regh = NULL;
7283dec9fcdSqs 	dev_regs->hxge_pciregh = NULL;
7293dec9fcdSqs 	dev_regs->hxge_msix_regh = NULL;
7303dec9fcdSqs 
7313dec9fcdSqs 	(void) ddi_dev_regsize(hxgep->dip, 0, &regsize);
7323dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
7333dec9fcdSqs 	    "hxge_map_regs: pci config size 0x%x", regsize));
7343dec9fcdSqs 
7353dec9fcdSqs 	ddi_status = ddi_regs_map_setup(hxgep->dip, 0,
7363dec9fcdSqs 	    (caddr_t *)&(dev_regs->hxge_pciregp), 0, 0,
7373dec9fcdSqs 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_pciregh);
7383dec9fcdSqs 	if (ddi_status != DDI_SUCCESS) {
7393dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7403dec9fcdSqs 		    "ddi_map_regs, hxge bus config regs failed"));
7413dec9fcdSqs 		goto hxge_map_regs_fail0;
7423dec9fcdSqs 	}
7433dec9fcdSqs 
7443dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
7453dec9fcdSqs 	    "hxge_map_reg: PCI config addr 0x%0llx handle 0x%0llx",
7463dec9fcdSqs 	    dev_regs->hxge_pciregp,
7473dec9fcdSqs 	    dev_regs->hxge_pciregh));
7483dec9fcdSqs 
7493dec9fcdSqs 	(void) ddi_dev_regsize(hxgep->dip, 1, &regsize);
7503dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
7513dec9fcdSqs 	    "hxge_map_regs: pio size 0x%x", regsize));
7523dec9fcdSqs 
7533dec9fcdSqs 	/* set up the device mapped register */
7543dec9fcdSqs 	ddi_status = ddi_regs_map_setup(hxgep->dip, 1,
7553dec9fcdSqs 	    (caddr_t *)&(dev_regs->hxge_regp), 0, 0,
7563dec9fcdSqs 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_regh);
7573dec9fcdSqs 
7583dec9fcdSqs 	if (ddi_status != DDI_SUCCESS) {
7593dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7603dec9fcdSqs 		    "ddi_map_regs for Hydra global reg failed"));
7613dec9fcdSqs 		goto hxge_map_regs_fail1;
7623dec9fcdSqs 	}
7633dec9fcdSqs 
7643dec9fcdSqs 	/* set up the msi/msi-x mapped register */
7653dec9fcdSqs 	(void) ddi_dev_regsize(hxgep->dip, 2, &regsize);
7663dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
7673dec9fcdSqs 	    "hxge_map_regs: msix size 0x%x", regsize));
7683dec9fcdSqs 
7693dec9fcdSqs 	ddi_status = ddi_regs_map_setup(hxgep->dip, 2,
7703dec9fcdSqs 	    (caddr_t *)&(dev_regs->hxge_msix_regp), 0, 0,
7713dec9fcdSqs 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_msix_regh);
7723dec9fcdSqs 
7733dec9fcdSqs 	if (ddi_status != DDI_SUCCESS) {
7743dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7753dec9fcdSqs 		    "ddi_map_regs for msi reg failed"));
7763dec9fcdSqs 		goto hxge_map_regs_fail2;
7773dec9fcdSqs 	}
7783dec9fcdSqs 
7793dec9fcdSqs 	hxgep->dev_regs = dev_regs;
7803dec9fcdSqs 
7813dec9fcdSqs 	HPI_PCI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_pciregh);
7823dec9fcdSqs 	HPI_PCI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_pciregp);
7833dec9fcdSqs 	HPI_MSI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_msix_regh);
7843dec9fcdSqs 	HPI_MSI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_msix_regp);
7853dec9fcdSqs 
7863dec9fcdSqs 	HPI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh);
7873dec9fcdSqs 	HPI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp);
7883dec9fcdSqs 
7893dec9fcdSqs 	HPI_REG_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh);
7903dec9fcdSqs 	HPI_REG_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp);
7913dec9fcdSqs 
7923dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_reg: hardware addr 0x%0llx "
7933dec9fcdSqs 	    " handle 0x%0llx", dev_regs->hxge_regp, dev_regs->hxge_regh));
7943dec9fcdSqs 
7953dec9fcdSqs 	goto hxge_map_regs_exit;
7963dec9fcdSqs 
7973dec9fcdSqs hxge_map_regs_fail3:
7983dec9fcdSqs 	if (dev_regs->hxge_msix_regh) {
7993dec9fcdSqs 		ddi_regs_map_free(&dev_regs->hxge_msix_regh);
8003dec9fcdSqs 	}
8013dec9fcdSqs 
8023dec9fcdSqs hxge_map_regs_fail2:
8033dec9fcdSqs 	if (dev_regs->hxge_regh) {
8043dec9fcdSqs 		ddi_regs_map_free(&dev_regs->hxge_regh);
8053dec9fcdSqs 	}
8063dec9fcdSqs 
8073dec9fcdSqs hxge_map_regs_fail1:
8083dec9fcdSqs 	if (dev_regs->hxge_pciregh) {
8093dec9fcdSqs 		ddi_regs_map_free(&dev_regs->hxge_pciregh);
8103dec9fcdSqs 	}
8113dec9fcdSqs 
8123dec9fcdSqs hxge_map_regs_fail0:
8133dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "Freeing register set memory"));
8143dec9fcdSqs 	kmem_free(dev_regs, sizeof (dev_regs_t));
8153dec9fcdSqs 
8163dec9fcdSqs hxge_map_regs_exit:
8173dec9fcdSqs 	if (ddi_status != DDI_SUCCESS)
8183dec9fcdSqs 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
8193dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_map_regs"));
8203dec9fcdSqs 	return (status);
8213dec9fcdSqs }
8223dec9fcdSqs 
8233dec9fcdSqs static void
8243dec9fcdSqs hxge_unmap_regs(p_hxge_t hxgep)
8253dec9fcdSqs {
8263dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unmap_regs"));
8273dec9fcdSqs 	if (hxgep->dev_regs) {
8283dec9fcdSqs 		if (hxgep->dev_regs->hxge_pciregh) {
8293dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8303dec9fcdSqs 			    "==> hxge_unmap_regs: bus"));
8313dec9fcdSqs 			ddi_regs_map_free(&hxgep->dev_regs->hxge_pciregh);
8323dec9fcdSqs 			hxgep->dev_regs->hxge_pciregh = NULL;
8333dec9fcdSqs 		}
8343dec9fcdSqs 
8353dec9fcdSqs 		if (hxgep->dev_regs->hxge_regh) {
8363dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8373dec9fcdSqs 			    "==> hxge_unmap_regs: device registers"));
8383dec9fcdSqs 			ddi_regs_map_free(&hxgep->dev_regs->hxge_regh);
8393dec9fcdSqs 			hxgep->dev_regs->hxge_regh = NULL;
8403dec9fcdSqs 		}
8413dec9fcdSqs 
8423dec9fcdSqs 		if (hxgep->dev_regs->hxge_msix_regh) {
8433dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8443dec9fcdSqs 			    "==> hxge_unmap_regs: device interrupts"));
8453dec9fcdSqs 			ddi_regs_map_free(&hxgep->dev_regs->hxge_msix_regh);
8463dec9fcdSqs 			hxgep->dev_regs->hxge_msix_regh = NULL;
8473dec9fcdSqs 		}
8483dec9fcdSqs 		kmem_free(hxgep->dev_regs, sizeof (dev_regs_t));
8493dec9fcdSqs 		hxgep->dev_regs = NULL;
8503dec9fcdSqs 	}
8513dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_unmap_regs"));
8523dec9fcdSqs }
8533dec9fcdSqs 
8543dec9fcdSqs static hxge_status_t
8553dec9fcdSqs hxge_setup_mutexes(p_hxge_t hxgep)
8563dec9fcdSqs {
8573dec9fcdSqs 	int		ddi_status = DDI_SUCCESS;
8583dec9fcdSqs 	hxge_status_t	status = HXGE_OK;
8593dec9fcdSqs 
8603dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_mutexes"));
8613dec9fcdSqs 
8623dec9fcdSqs 	/*
8633dec9fcdSqs 	 * Get the interrupt cookie so the mutexes can be Initialised.
8643dec9fcdSqs 	 */
8653dec9fcdSqs 	ddi_status = ddi_get_iblock_cookie(hxgep->dip, 0,
8663dec9fcdSqs 	    &hxgep->interrupt_cookie);
8673dec9fcdSqs 
8683dec9fcdSqs 	if (ddi_status != DDI_SUCCESS) {
8693dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
8703dec9fcdSqs 		    "<== hxge_setup_mutexes: failed 0x%x", ddi_status));
8713dec9fcdSqs 		goto hxge_setup_mutexes_exit;
8723dec9fcdSqs 	}
8733dec9fcdSqs 
8743dec9fcdSqs 	/*
8753dec9fcdSqs 	 * Initialize mutex's for this device.
8763dec9fcdSqs 	 */
8773dec9fcdSqs 	MUTEX_INIT(hxgep->genlock, NULL,
8783dec9fcdSqs 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
8793dec9fcdSqs 	MUTEX_INIT(&hxgep->ouraddr_lock, NULL,
8803dec9fcdSqs 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
8813dec9fcdSqs 	RW_INIT(&hxgep->filter_lock, NULL,
8823dec9fcdSqs 	    RW_DRIVER, (void *) hxgep->interrupt_cookie);
883fe930412Sqs 	MUTEX_INIT(&hxgep->pio_lock, NULL,
884fe930412Sqs 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
885*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_INIT(&hxgep->timeout.lock, NULL,
886*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
8873dec9fcdSqs 
8883dec9fcdSqs hxge_setup_mutexes_exit:
8893dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
8903dec9fcdSqs 	    "<== hxge_setup_mutexes status = %x", status));
8913dec9fcdSqs 
8923dec9fcdSqs 	if (ddi_status != DDI_SUCCESS)
8933dec9fcdSqs 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
8943dec9fcdSqs 
8953dec9fcdSqs 	return (status);
8963dec9fcdSqs }
8973dec9fcdSqs 
8983dec9fcdSqs static void
8993dec9fcdSqs hxge_destroy_mutexes(p_hxge_t hxgep)
9003dec9fcdSqs {
9013dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_mutexes"));
9023dec9fcdSqs 	RW_DESTROY(&hxgep->filter_lock);
9033dec9fcdSqs 	MUTEX_DESTROY(&hxgep->ouraddr_lock);
9043dec9fcdSqs 	MUTEX_DESTROY(hxgep->genlock);
905fe930412Sqs 	MUTEX_DESTROY(&hxgep->pio_lock);
906*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_DESTROY(&hxgep->timeout.lock);
9073dec9fcdSqs 
9083dec9fcdSqs 	if (hxge_debug_init == 1) {
9093dec9fcdSqs 		MUTEX_DESTROY(&hxgedebuglock);
9103dec9fcdSqs 		hxge_debug_init = 0;
9113dec9fcdSqs 	}
9123dec9fcdSqs 
9133dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_mutexes"));
9143dec9fcdSqs }
9153dec9fcdSqs 
9163dec9fcdSqs hxge_status_t
9173dec9fcdSqs hxge_init(p_hxge_t hxgep)
9183dec9fcdSqs {
9193dec9fcdSqs 	hxge_status_t status = HXGE_OK;
9203dec9fcdSqs 
9213dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, STR_CTL, "==> hxge_init"));
9223dec9fcdSqs 
9233dec9fcdSqs 	if (hxgep->drv_state & STATE_HW_INITIALIZED) {
9243dec9fcdSqs 		return (status);
9253dec9fcdSqs 	}
9263dec9fcdSqs 
9273dec9fcdSqs 	/*
9283dec9fcdSqs 	 * Allocate system memory for the receive/transmit buffer blocks and
9293dec9fcdSqs 	 * receive/transmit descriptor rings.
9303dec9fcdSqs 	 */
9313dec9fcdSqs 	status = hxge_alloc_mem_pool(hxgep);
9323dec9fcdSqs 	if (status != HXGE_OK) {
9333dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "alloc mem failed\n"));
9343dec9fcdSqs 		goto hxge_init_fail1;
9353dec9fcdSqs 	}
9363dec9fcdSqs 
9373dec9fcdSqs 	/*
9383dec9fcdSqs 	 * Initialize and enable TXDMA channels.
9393dec9fcdSqs 	 */
9403dec9fcdSqs 	status = hxge_init_txdma_channels(hxgep);
9413dec9fcdSqs 	if (status != HXGE_OK) {
9423dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init txdma failed\n"));
9433dec9fcdSqs 		goto hxge_init_fail3;
9443dec9fcdSqs 	}
9453dec9fcdSqs 
9463dec9fcdSqs 	/*
9473dec9fcdSqs 	 * Initialize and enable RXDMA channels.
9483dec9fcdSqs 	 */
9493dec9fcdSqs 	status = hxge_init_rxdma_channels(hxgep);
9503dec9fcdSqs 	if (status != HXGE_OK) {
9513dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init rxdma failed\n"));
9523dec9fcdSqs 		goto hxge_init_fail4;
9533dec9fcdSqs 	}
9543dec9fcdSqs 
9553dec9fcdSqs 	/*
9563dec9fcdSqs 	 * Initialize TCAM
9573dec9fcdSqs 	 */
9583dec9fcdSqs 	status = hxge_classify_init(hxgep);
9593dec9fcdSqs 	if (status != HXGE_OK) {
9603dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init classify failed\n"));
9613dec9fcdSqs 		goto hxge_init_fail5;
9623dec9fcdSqs 	}
9633dec9fcdSqs 
9643dec9fcdSqs 	/*
9653dec9fcdSqs 	 * Initialize the VMAC block.
9663dec9fcdSqs 	 */
9673dec9fcdSqs 	status = hxge_vmac_init(hxgep);
9683dec9fcdSqs 	if (status != HXGE_OK) {
9693dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init MAC failed\n"));
9703dec9fcdSqs 		goto hxge_init_fail5;
9713dec9fcdSqs 	}
9723dec9fcdSqs 
9733dec9fcdSqs 	/* Bringup - this may be unnecessary when PXE and FCODE available */
9743dec9fcdSqs 	status = hxge_pfc_set_default_mac_addr(hxgep);
9753dec9fcdSqs 	if (status != HXGE_OK) {
9763dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9773dec9fcdSqs 		    "Default Address Failure\n"));
9783dec9fcdSqs 		goto hxge_init_fail5;
9793dec9fcdSqs 	}
9803dec9fcdSqs 
9813dec9fcdSqs 	hxge_intrs_enable(hxgep);
9823dec9fcdSqs 
9833dec9fcdSqs 	/*
9843dec9fcdSqs 	 * Enable hardware interrupts.
9853dec9fcdSqs 	 */
9863dec9fcdSqs 	hxge_intr_hw_enable(hxgep);
9873dec9fcdSqs 	hxgep->drv_state |= STATE_HW_INITIALIZED;
9883dec9fcdSqs 
9893dec9fcdSqs 	goto hxge_init_exit;
9903dec9fcdSqs 
9913dec9fcdSqs hxge_init_fail5:
9923dec9fcdSqs 	hxge_uninit_rxdma_channels(hxgep);
9933dec9fcdSqs hxge_init_fail4:
9943dec9fcdSqs 	hxge_uninit_txdma_channels(hxgep);
9953dec9fcdSqs hxge_init_fail3:
9963dec9fcdSqs 	hxge_free_mem_pool(hxgep);
9973dec9fcdSqs hxge_init_fail1:
9983dec9fcdSqs 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9993dec9fcdSqs 	    "<== hxge_init status (failed) = 0x%08x", status));
10003dec9fcdSqs 	return (status);
10013dec9fcdSqs 
10023dec9fcdSqs hxge_init_exit:
10033dec9fcdSqs 
10043dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_init status = 0x%08x",
10053dec9fcdSqs 	    status));
10063dec9fcdSqs 
10073dec9fcdSqs 	return (status);
10083dec9fcdSqs }
10093dec9fcdSqs 
10103dec9fcdSqs timeout_id_t
10113dec9fcdSqs hxge_start_timer(p_hxge_t hxgep, fptrv_t func, int msec)
10123dec9fcdSqs {
10133dec9fcdSqs 	if ((hxgep->suspended == 0) || (hxgep->suspended == DDI_RESUME)) {
10143dec9fcdSqs 		return (timeout(func, (caddr_t)hxgep,
10153dec9fcdSqs 		    drv_usectohz(1000 * msec)));
10163dec9fcdSqs 	}
10173dec9fcdSqs 	return (NULL);
10183dec9fcdSqs }
10193dec9fcdSqs 
10203dec9fcdSqs /*ARGSUSED*/
10213dec9fcdSqs void
10223dec9fcdSqs hxge_stop_timer(p_hxge_t hxgep, timeout_id_t timerid)
10233dec9fcdSqs {
10243dec9fcdSqs 	if (timerid) {
10253dec9fcdSqs 		(void) untimeout(timerid);
10263dec9fcdSqs 	}
10273dec9fcdSqs }
10283dec9fcdSqs 
10293dec9fcdSqs void
10303dec9fcdSqs hxge_uninit(p_hxge_t hxgep)
10313dec9fcdSqs {
10323dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_uninit"));
10333dec9fcdSqs 
10343dec9fcdSqs 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
10353dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL,
10363dec9fcdSqs 		    "==> hxge_uninit: not initialized"));
10373dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit"));
10383dec9fcdSqs 		return;
10393dec9fcdSqs 	}
10403dec9fcdSqs 
10413dec9fcdSqs 	/* Stop timer */
10423dec9fcdSqs 	if (hxgep->hxge_timerid) {
10433dec9fcdSqs 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
10443dec9fcdSqs 		hxgep->hxge_timerid = 0;
10453dec9fcdSqs 	}
10463dec9fcdSqs 
10473dec9fcdSqs 	(void) hxge_intr_hw_disable(hxgep);
10483dec9fcdSqs 
10493dec9fcdSqs 	/* Reset the receive VMAC side.  */
10503dec9fcdSqs 	(void) hxge_rx_vmac_disable(hxgep);
10513dec9fcdSqs 
10523dec9fcdSqs 	/* Free classification resources */
10533dec9fcdSqs 	(void) hxge_classify_uninit(hxgep);
10543dec9fcdSqs 
10553dec9fcdSqs 	/* Reset the transmit/receive DMA side.  */
10563dec9fcdSqs 	(void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_STOP);
10573dec9fcdSqs 	(void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_STOP);
10583dec9fcdSqs 
10593dec9fcdSqs 	hxge_uninit_txdma_channels(hxgep);
10603dec9fcdSqs 	hxge_uninit_rxdma_channels(hxgep);
10613dec9fcdSqs 
10623dec9fcdSqs 	/* Reset the transmit VMAC side.  */
10633dec9fcdSqs 	(void) hxge_tx_vmac_disable(hxgep);
10643dec9fcdSqs 
10653dec9fcdSqs 	hxge_free_mem_pool(hxgep);
10663dec9fcdSqs 
10673dec9fcdSqs 	hxgep->drv_state &= ~STATE_HW_INITIALIZED;
10683dec9fcdSqs 
10693dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit"));
10703dec9fcdSqs }
10713dec9fcdSqs 
10723dec9fcdSqs void
10733dec9fcdSqs hxge_get64(p_hxge_t hxgep, p_mblk_t mp)
10743dec9fcdSqs {
10753dec9fcdSqs #if defined(__i386)
10763dec9fcdSqs 	size_t		reg;
10773dec9fcdSqs #else
10783dec9fcdSqs 	uint64_t	reg;
10793dec9fcdSqs #endif
10803dec9fcdSqs 	uint64_t	regdata;
10813dec9fcdSqs 	int		i, retry;
10823dec9fcdSqs 
10833dec9fcdSqs 	bcopy((char *)mp->b_rptr, (char *)&reg, sizeof (uint64_t));
10843dec9fcdSqs 	regdata = 0;
10853dec9fcdSqs 	retry = 1;
10863dec9fcdSqs 
10873dec9fcdSqs 	for (i = 0; i < retry; i++) {
10883dec9fcdSqs 		HXGE_REG_RD64(hxgep->hpi_handle, reg, &regdata);
10893dec9fcdSqs 	}
10903dec9fcdSqs 	bcopy((char *)&regdata, (char *)mp->b_rptr, sizeof (uint64_t));
10913dec9fcdSqs }
10923dec9fcdSqs 
10933dec9fcdSqs void
10943dec9fcdSqs hxge_put64(p_hxge_t hxgep, p_mblk_t mp)
10953dec9fcdSqs {
10963dec9fcdSqs #if defined(__i386)
10973dec9fcdSqs 	size_t		reg;
10983dec9fcdSqs #else
10993dec9fcdSqs 	uint64_t	reg;
11003dec9fcdSqs #endif
11013dec9fcdSqs 	uint64_t	buf[2];
11023dec9fcdSqs 
11033dec9fcdSqs 	bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t));
11043dec9fcdSqs #if defined(__i386)
11053dec9fcdSqs 	reg = (size_t)buf[0];
11063dec9fcdSqs #else
11073dec9fcdSqs 	reg = buf[0];
11083dec9fcdSqs #endif
11093dec9fcdSqs 
11103dec9fcdSqs 	HXGE_HPI_PIO_WRITE64(hxgep->hpi_handle, reg, buf[1]);
11113dec9fcdSqs }
11123dec9fcdSqs 
11133dec9fcdSqs /*ARGSUSED*/
11143dec9fcdSqs /*VARARGS*/
11153dec9fcdSqs void
11163dec9fcdSqs hxge_debug_msg(p_hxge_t hxgep, uint64_t level, char *fmt, ...)
11173dec9fcdSqs {
11183dec9fcdSqs 	char		msg_buffer[1048];
11193dec9fcdSqs 	char		prefix_buffer[32];
11203dec9fcdSqs 	int		instance;
11213dec9fcdSqs 	uint64_t	debug_level;
11223dec9fcdSqs 	int		cmn_level = CE_CONT;
11233dec9fcdSqs 	va_list		ap;
11243dec9fcdSqs 
11253dec9fcdSqs 	debug_level = (hxgep == NULL) ? hxge_debug_level :
11263dec9fcdSqs 	    hxgep->hxge_debug_level;
11273dec9fcdSqs 
11283dec9fcdSqs 	if ((level & debug_level) || (level == HXGE_NOTE) ||
11293dec9fcdSqs 	    (level == HXGE_ERR_CTL)) {
11303dec9fcdSqs 		/* do the msg processing */
11313dec9fcdSqs 		if (hxge_debug_init == 0) {
11323dec9fcdSqs 			MUTEX_INIT(&hxgedebuglock, NULL, MUTEX_DRIVER, NULL);
11333dec9fcdSqs 			hxge_debug_init = 1;
11343dec9fcdSqs 		}
11353dec9fcdSqs 
11363dec9fcdSqs 		MUTEX_ENTER(&hxgedebuglock);
11373dec9fcdSqs 
11383dec9fcdSqs 		if ((level & HXGE_NOTE)) {
11393dec9fcdSqs 			cmn_level = CE_NOTE;
11403dec9fcdSqs 		}
11413dec9fcdSqs 
11423dec9fcdSqs 		if (level & HXGE_ERR_CTL) {
11433dec9fcdSqs 			cmn_level = CE_WARN;
11443dec9fcdSqs 		}
11453dec9fcdSqs 
11463dec9fcdSqs 		va_start(ap, fmt);
11473dec9fcdSqs 		(void) vsprintf(msg_buffer, fmt, ap);
11483dec9fcdSqs 		va_end(ap);
11493dec9fcdSqs 
11503dec9fcdSqs 		if (hxgep == NULL) {
11513dec9fcdSqs 			instance = -1;
11523dec9fcdSqs 			(void) sprintf(prefix_buffer, "%s :", "hxge");
11533dec9fcdSqs 		} else {
11543dec9fcdSqs 			instance = hxgep->instance;
11553dec9fcdSqs 			(void) sprintf(prefix_buffer,
11563dec9fcdSqs 			    "%s%d :", "hxge", instance);
11573dec9fcdSqs 		}
11583dec9fcdSqs 
11593dec9fcdSqs 		MUTEX_EXIT(&hxgedebuglock);
11603dec9fcdSqs 		cmn_err(cmn_level, "%s %s\n", prefix_buffer, msg_buffer);
11613dec9fcdSqs 	}
11623dec9fcdSqs }
11633dec9fcdSqs 
11643dec9fcdSqs char *
11653dec9fcdSqs hxge_dump_packet(char *addr, int size)
11663dec9fcdSqs {
11673dec9fcdSqs 	uchar_t		*ap = (uchar_t *)addr;
11683dec9fcdSqs 	int		i;
11693dec9fcdSqs 	static char	etherbuf[1024];
11703dec9fcdSqs 	char		*cp = etherbuf;
11713dec9fcdSqs 	char		digits[] = "0123456789abcdef";
11723dec9fcdSqs 
11733dec9fcdSqs 	if (!size)
11743dec9fcdSqs 		size = 60;
11753dec9fcdSqs 
11763dec9fcdSqs 	if (size > MAX_DUMP_SZ) {
11773dec9fcdSqs 		/* Dump the leading bytes */
11783dec9fcdSqs 		for (i = 0; i < MAX_DUMP_SZ / 2; i++) {
11793dec9fcdSqs 			if (*ap > 0x0f)
11803dec9fcdSqs 				*cp++ = digits[*ap >> 4];
11813dec9fcdSqs 			*cp++ = digits[*ap++ & 0xf];
11823dec9fcdSqs 			*cp++ = ':';
11833dec9fcdSqs 		}
11843dec9fcdSqs 		for (i = 0; i < 20; i++)
11853dec9fcdSqs 			*cp++ = '.';
11863dec9fcdSqs 		/* Dump the last MAX_DUMP_SZ/2 bytes */
11873dec9fcdSqs 		ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ / 2));
11883dec9fcdSqs 		for (i = 0; i < MAX_DUMP_SZ / 2; i++) {
11893dec9fcdSqs 			if (*ap > 0x0f)
11903dec9fcdSqs 				*cp++ = digits[*ap >> 4];
11913dec9fcdSqs 			*cp++ = digits[*ap++ & 0xf];
11923dec9fcdSqs 			*cp++ = ':';
11933dec9fcdSqs 		}
11943dec9fcdSqs 	} else {
11953dec9fcdSqs 		for (i = 0; i < size; i++) {
11963dec9fcdSqs 			if (*ap > 0x0f)
11973dec9fcdSqs 				*cp++ = digits[*ap >> 4];
11983dec9fcdSqs 			*cp++ = digits[*ap++ & 0xf];
11993dec9fcdSqs 			*cp++ = ':';
12003dec9fcdSqs 		}
12013dec9fcdSqs 	}
12023dec9fcdSqs 	*--cp = 0;
12033dec9fcdSqs 	return (etherbuf);
12043dec9fcdSqs }
12053dec9fcdSqs 
12063dec9fcdSqs static void
12073dec9fcdSqs hxge_suspend(p_hxge_t hxgep)
12083dec9fcdSqs {
12093dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_suspend"));
12103dec9fcdSqs 
12113dec9fcdSqs 	hxge_intrs_disable(hxgep);
12123dec9fcdSqs 	hxge_destroy_dev(hxgep);
12133dec9fcdSqs 
1214*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	/* Stop the link status timer */
1215*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_ENTER(&hxgep->timeout.lock);
1216*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if (hxgep->timeout.id)
1217*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		(void) untimeout(hxgep->timeout.id);
1218*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_EXIT(&hxgep->timeout.lock);
1219*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
12203dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_suspend"));
12213dec9fcdSqs }
12223dec9fcdSqs 
12233dec9fcdSqs static hxge_status_t
12243dec9fcdSqs hxge_resume(p_hxge_t hxgep)
12253dec9fcdSqs {
12263dec9fcdSqs 	hxge_status_t status = HXGE_OK;
12273dec9fcdSqs 
12283dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_resume"));
12293dec9fcdSqs 	hxgep->suspended = DDI_RESUME;
12303dec9fcdSqs 
12313dec9fcdSqs 	(void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_START);
12323dec9fcdSqs 	(void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_START);
12333dec9fcdSqs 
12343dec9fcdSqs 	(void) hxge_rx_vmac_enable(hxgep);
12353dec9fcdSqs 	(void) hxge_tx_vmac_enable(hxgep);
12363dec9fcdSqs 
12373dec9fcdSqs 	hxge_intrs_enable(hxgep);
12383dec9fcdSqs 
12393dec9fcdSqs 	hxgep->suspended = 0;
12403dec9fcdSqs 
1241*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	/* Resume the link status timer */
1242*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_ENTER(&hxgep->timeout.lock);
1243*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep,
1244*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	    hxgep->timeout.ticks);
1245*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_EXIT(&hxgep->timeout.lock);
1246*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
12473dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
12483dec9fcdSqs 	    "<== hxge_resume status = 0x%x", status));
12493dec9fcdSqs 
12503dec9fcdSqs 	return (status);
12513dec9fcdSqs }
12523dec9fcdSqs 
12533dec9fcdSqs hxge_status_t
12543dec9fcdSqs hxge_setup_dev(p_hxge_t hxgep)
12553dec9fcdSqs {
12563dec9fcdSqs 	hxge_status_t status = HXGE_OK;
12573dec9fcdSqs 
12583dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_dev"));
12593dec9fcdSqs 
12603dec9fcdSqs 	status = hxge_link_init(hxgep);
12613dec9fcdSqs 	if (fm_check_acc_handle(hxgep->dev_regs->hxge_regh) != DDI_FM_OK) {
12623dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
12633dec9fcdSqs 		    "Bad register acc handle"));
12643dec9fcdSqs 		status = HXGE_ERROR;
12653dec9fcdSqs 	}
12663dec9fcdSqs 
12673dec9fcdSqs 	if (status != HXGE_OK) {
12683dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MAC_CTL,
12693dec9fcdSqs 		    " hxge_setup_dev status (link init 0x%08x)", status));
12703dec9fcdSqs 		goto hxge_setup_dev_exit;
12713dec9fcdSqs 	}
12723dec9fcdSqs 
12733dec9fcdSqs hxge_setup_dev_exit:
12743dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
12753dec9fcdSqs 	    "<== hxge_setup_dev status = 0x%08x", status));
12763dec9fcdSqs 
12773dec9fcdSqs 	return (status);
12783dec9fcdSqs }
12793dec9fcdSqs 
12803dec9fcdSqs static void
12813dec9fcdSqs hxge_destroy_dev(p_hxge_t hxgep)
12823dec9fcdSqs {
12833dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_dev"));
12843dec9fcdSqs 
12853dec9fcdSqs 	(void) hxge_hw_stop(hxgep);
12863dec9fcdSqs 
12873dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_dev"));
12883dec9fcdSqs }
12893dec9fcdSqs 
12903dec9fcdSqs static hxge_status_t
12913dec9fcdSqs hxge_setup_system_dma_pages(p_hxge_t hxgep)
12923dec9fcdSqs {
12933dec9fcdSqs 	int			ddi_status = DDI_SUCCESS;
12943dec9fcdSqs 	uint_t			count;
12953dec9fcdSqs 	ddi_dma_cookie_t	cookie;
12963dec9fcdSqs 	uint_t			iommu_pagesize;
12973dec9fcdSqs 	hxge_status_t		status = HXGE_OK;
12983dec9fcdSqs 
12993dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_system_dma_pages"));
13003dec9fcdSqs 
13013dec9fcdSqs 	hxgep->sys_page_sz = ddi_ptob(hxgep->dip, (ulong_t)1);
13023dec9fcdSqs 	iommu_pagesize = dvma_pagesize(hxgep->dip);
13033dec9fcdSqs 
13043dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
13053dec9fcdSqs 	    " hxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
13063dec9fcdSqs 	    " default_block_size %d iommu_pagesize %d",
13073dec9fcdSqs 	    hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1),
13083dec9fcdSqs 	    hxgep->rx_default_block_size, iommu_pagesize));
13093dec9fcdSqs 
13103dec9fcdSqs 	if (iommu_pagesize != 0) {
13113dec9fcdSqs 		if (hxgep->sys_page_sz == iommu_pagesize) {
13123dec9fcdSqs 			/* Hydra support up to 8K pages */
13133dec9fcdSqs 			if (iommu_pagesize > 0x2000)
13143dec9fcdSqs 				hxgep->sys_page_sz = 0x2000;
13153dec9fcdSqs 		} else {
13163dec9fcdSqs 			if (hxgep->sys_page_sz > iommu_pagesize)
13173dec9fcdSqs 				hxgep->sys_page_sz = iommu_pagesize;
13183dec9fcdSqs 		}
13193dec9fcdSqs 	}
13203dec9fcdSqs 
13213dec9fcdSqs 	hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1);
13223dec9fcdSqs 
13233dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
13243dec9fcdSqs 	    "==> hxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
13253dec9fcdSqs 	    "default_block_size %d page mask %d",
13263dec9fcdSqs 	    hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1),
13273dec9fcdSqs 	    hxgep->rx_default_block_size, hxgep->sys_page_mask));
13283dec9fcdSqs 
13293dec9fcdSqs 	switch (hxgep->sys_page_sz) {
13303dec9fcdSqs 	default:
13313dec9fcdSqs 		hxgep->sys_page_sz = 0x1000;
13323dec9fcdSqs 		hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1);
13333dec9fcdSqs 		hxgep->rx_default_block_size = 0x1000;
13343dec9fcdSqs 		hxgep->rx_bksize_code = RBR_BKSIZE_4K;
13353dec9fcdSqs 		break;
13363dec9fcdSqs 	case 0x1000:
13373dec9fcdSqs 		hxgep->rx_default_block_size = 0x1000;
13383dec9fcdSqs 		hxgep->rx_bksize_code = RBR_BKSIZE_4K;
13393dec9fcdSqs 		break;
13403dec9fcdSqs 	case 0x2000:
13413dec9fcdSqs 		hxgep->rx_default_block_size = 0x2000;
13423dec9fcdSqs 		hxgep->rx_bksize_code = RBR_BKSIZE_8K;
13433dec9fcdSqs 		break;
13443dec9fcdSqs 	}
13453dec9fcdSqs 
13463dec9fcdSqs 	hxge_rx_dma_attr.dma_attr_align = hxgep->sys_page_sz;
13473dec9fcdSqs 	hxge_tx_dma_attr.dma_attr_align = hxgep->sys_page_sz;
13483dec9fcdSqs 	hxge_desc_dma_attr.dma_attr_align = hxgep->sys_page_sz;
13493dec9fcdSqs 
13503dec9fcdSqs 	/*
13513dec9fcdSqs 	 * Get the system DMA burst size.
13523dec9fcdSqs 	 */
13533dec9fcdSqs 	ddi_status = ddi_dma_alloc_handle(hxgep->dip, &hxge_tx_dma_attr,
13543dec9fcdSqs 	    DDI_DMA_DONTWAIT, 0, &hxgep->dmasparehandle);
13553dec9fcdSqs 	if (ddi_status != DDI_SUCCESS) {
13563dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
13573dec9fcdSqs 		    "ddi_dma_alloc_handle: failed status 0x%x", ddi_status));
13583dec9fcdSqs 		goto hxge_get_soft_properties_exit;
13593dec9fcdSqs 	}
13603dec9fcdSqs 
13613dec9fcdSqs 	ddi_status = ddi_dma_addr_bind_handle(hxgep->dmasparehandle, NULL,
13623dec9fcdSqs 	    (caddr_t)hxgep->dmasparehandle, sizeof (hxgep->dmasparehandle),
13633dec9fcdSqs 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0,
13643dec9fcdSqs 	    &cookie, &count);
13653dec9fcdSqs 	if (ddi_status != DDI_DMA_MAPPED) {
13663dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
13673dec9fcdSqs 		    "Binding spare handle to find system burstsize failed."));
13683dec9fcdSqs 		ddi_status = DDI_FAILURE;
13693dec9fcdSqs 		goto hxge_get_soft_properties_fail1;
13703dec9fcdSqs 	}
13713dec9fcdSqs 
13723dec9fcdSqs 	hxgep->sys_burst_sz = ddi_dma_burstsizes(hxgep->dmasparehandle);
13733dec9fcdSqs 	(void) ddi_dma_unbind_handle(hxgep->dmasparehandle);
13743dec9fcdSqs 
13753dec9fcdSqs hxge_get_soft_properties_fail1:
13763dec9fcdSqs 	ddi_dma_free_handle(&hxgep->dmasparehandle);
13773dec9fcdSqs 
13783dec9fcdSqs hxge_get_soft_properties_exit:
13793dec9fcdSqs 
13803dec9fcdSqs 	if (ddi_status != DDI_SUCCESS)
13813dec9fcdSqs 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
13823dec9fcdSqs 
13833dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
13843dec9fcdSqs 	    "<== hxge_setup_system_dma_pages status = 0x%08x", status));
13853dec9fcdSqs 
13863dec9fcdSqs 	return (status);
13873dec9fcdSqs }
13883dec9fcdSqs 
13893dec9fcdSqs hxge_status_t
13903dec9fcdSqs hxge_alloc_mem_pool(p_hxge_t hxgep)
13913dec9fcdSqs {
13923dec9fcdSqs 	hxge_status_t status = HXGE_OK;
13933dec9fcdSqs 
13943dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_alloc_mem_pool"));
13953dec9fcdSqs 
13963dec9fcdSqs 	status = hxge_alloc_rx_mem_pool(hxgep);
13973dec9fcdSqs 	if (status != HXGE_OK) {
13983dec9fcdSqs 		return (HXGE_ERROR);
13993dec9fcdSqs 	}
14003dec9fcdSqs 
14013dec9fcdSqs 	status = hxge_alloc_tx_mem_pool(hxgep);
14023dec9fcdSqs 	if (status != HXGE_OK) {
14033dec9fcdSqs 		hxge_free_rx_mem_pool(hxgep);
14043dec9fcdSqs 		return (HXGE_ERROR);
14053dec9fcdSqs 	}
14063dec9fcdSqs 
14073dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_alloc_mem_pool"));
14083dec9fcdSqs 	return (HXGE_OK);
14093dec9fcdSqs }
14103dec9fcdSqs 
14113dec9fcdSqs static void
14123dec9fcdSqs hxge_free_mem_pool(p_hxge_t hxgep)
14133dec9fcdSqs {
14143dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_mem_pool"));
14153dec9fcdSqs 
14163dec9fcdSqs 	hxge_free_rx_mem_pool(hxgep);
14173dec9fcdSqs 	hxge_free_tx_mem_pool(hxgep);
14183dec9fcdSqs 
14193dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_mem_pool"));
14203dec9fcdSqs }
14213dec9fcdSqs 
14223dec9fcdSqs static hxge_status_t
14233dec9fcdSqs hxge_alloc_rx_mem_pool(p_hxge_t hxgep)
14243dec9fcdSqs {
14253dec9fcdSqs 	int			i, j;
14263dec9fcdSqs 	uint32_t		ndmas, st_rdc;
14273dec9fcdSqs 	p_hxge_dma_pt_cfg_t	p_all_cfgp;
14283dec9fcdSqs 	p_hxge_hw_pt_cfg_t	p_cfgp;
14293dec9fcdSqs 	p_hxge_dma_pool_t	dma_poolp;
14303dec9fcdSqs 	p_hxge_dma_common_t	*dma_buf_p;
14313dec9fcdSqs 	p_hxge_dma_pool_t	dma_cntl_poolp;
14323dec9fcdSqs 	p_hxge_dma_common_t	*dma_cntl_p;
14333dec9fcdSqs 	size_t			rx_buf_alloc_size;
14343dec9fcdSqs 	size_t			rx_cntl_alloc_size;
14353dec9fcdSqs 	uint32_t		*num_chunks;	/* per dma */
14363dec9fcdSqs 	hxge_status_t		status = HXGE_OK;
14373dec9fcdSqs 
14383dec9fcdSqs 	uint32_t		hxge_port_rbr_size;
14393dec9fcdSqs 	uint32_t		hxge_port_rbr_spare_size;
14403dec9fcdSqs 	uint32_t		hxge_port_rcr_size;
14413dec9fcdSqs 
14423dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_mem_pool"));
14433dec9fcdSqs 
14443dec9fcdSqs 	p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
14453dec9fcdSqs 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
14463dec9fcdSqs 	st_rdc = p_cfgp->start_rdc;
14473dec9fcdSqs 	ndmas = p_cfgp->max_rdcs;
14483dec9fcdSqs 
14493dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
14503dec9fcdSqs 	    " hxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas));
14513dec9fcdSqs 
14523dec9fcdSqs 	/*
14533dec9fcdSqs 	 * Allocate memory for each receive DMA channel.
14543dec9fcdSqs 	 */
14553dec9fcdSqs 	dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t),
14563dec9fcdSqs 	    KM_SLEEP);
14573dec9fcdSqs 	dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
14583dec9fcdSqs 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
14593dec9fcdSqs 
14603dec9fcdSqs 	dma_cntl_poolp = (p_hxge_dma_pool_t)
14613dec9fcdSqs 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
14623dec9fcdSqs 	dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
14633dec9fcdSqs 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
14643dec9fcdSqs 
14653dec9fcdSqs 	num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas,
14663dec9fcdSqs 	    KM_SLEEP);
14673dec9fcdSqs 
14683dec9fcdSqs 	/*
14693dec9fcdSqs 	 * Assume that each DMA channel will be configured with default block
14703dec9fcdSqs 	 * size. rbr block counts are mod of batch count (16).
14713dec9fcdSqs 	 */
14723dec9fcdSqs 	hxge_port_rbr_size = p_all_cfgp->rbr_size;
14733dec9fcdSqs 	hxge_port_rcr_size = p_all_cfgp->rcr_size;
14743dec9fcdSqs 
14753dec9fcdSqs 	if (!hxge_port_rbr_size) {
14763dec9fcdSqs 		hxge_port_rbr_size = HXGE_RBR_RBB_DEFAULT;
14773dec9fcdSqs 	}
14783dec9fcdSqs 
14793dec9fcdSqs 	if (hxge_port_rbr_size % HXGE_RXDMA_POST_BATCH) {
14803dec9fcdSqs 		hxge_port_rbr_size = (HXGE_RXDMA_POST_BATCH *
14813dec9fcdSqs 		    (hxge_port_rbr_size / HXGE_RXDMA_POST_BATCH + 1));
14823dec9fcdSqs 	}
14833dec9fcdSqs 
14843dec9fcdSqs 	p_all_cfgp->rbr_size = hxge_port_rbr_size;
14853dec9fcdSqs 	hxge_port_rbr_spare_size = hxge_rbr_spare_size;
14863dec9fcdSqs 
14873dec9fcdSqs 	if (hxge_port_rbr_spare_size % HXGE_RXDMA_POST_BATCH) {
14883dec9fcdSqs 		hxge_port_rbr_spare_size = (HXGE_RXDMA_POST_BATCH *
14893dec9fcdSqs 		    (hxge_port_rbr_spare_size / HXGE_RXDMA_POST_BATCH + 1));
14903dec9fcdSqs 	}
14913dec9fcdSqs 
14923dec9fcdSqs 	rx_buf_alloc_size = (hxgep->rx_default_block_size *
14933dec9fcdSqs 	    (hxge_port_rbr_size + hxge_port_rbr_spare_size));
14943dec9fcdSqs 
14953dec9fcdSqs 	/*
14963dec9fcdSqs 	 * Addresses of receive block ring, receive completion ring and the
14973dec9fcdSqs 	 * mailbox must be all cache-aligned (64 bytes).
14983dec9fcdSqs 	 */
14993dec9fcdSqs 	rx_cntl_alloc_size = hxge_port_rbr_size + hxge_port_rbr_spare_size;
15003dec9fcdSqs 	rx_cntl_alloc_size *= (sizeof (rx_desc_t));
15013dec9fcdSqs 	rx_cntl_alloc_size += (sizeof (rcr_entry_t) * hxge_port_rcr_size);
15023dec9fcdSqs 	rx_cntl_alloc_size += sizeof (rxdma_mailbox_t);
15033dec9fcdSqs 
15043dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_alloc_rx_mem_pool: "
15053dec9fcdSqs 	    "hxge_port_rbr_size = %d hxge_port_rbr_spare_size = %d "
15063dec9fcdSqs 	    "hxge_port_rcr_size = %d rx_cntl_alloc_size = %d",
15073dec9fcdSqs 	    hxge_port_rbr_size, hxge_port_rbr_spare_size,
15083dec9fcdSqs 	    hxge_port_rcr_size, rx_cntl_alloc_size));
15093dec9fcdSqs 
15103dec9fcdSqs 	hxgep->hxge_port_rbr_size = hxge_port_rbr_size;
15113dec9fcdSqs 	hxgep->hxge_port_rcr_size = hxge_port_rcr_size;
15123dec9fcdSqs 
15133dec9fcdSqs 	/*
15143dec9fcdSqs 	 * Allocate memory for receive buffers and descriptor rings. Replace
15153dec9fcdSqs 	 * allocation functions with interface functions provided by the
15163dec9fcdSqs 	 * partition manager when it is available.
15173dec9fcdSqs 	 */
15183dec9fcdSqs 	/*
15193dec9fcdSqs 	 * Allocate memory for the receive buffer blocks.
15203dec9fcdSqs 	 */
15213dec9fcdSqs 	for (i = 0; i < ndmas; i++) {
15223dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
15233dec9fcdSqs 		    " hxge_alloc_rx_mem_pool to alloc mem: "
15243dec9fcdSqs 		    " dma %d dma_buf_p %llx &dma_buf_p %llx",
15253dec9fcdSqs 		    i, dma_buf_p[i], &dma_buf_p[i]));
15263dec9fcdSqs 
15273dec9fcdSqs 		num_chunks[i] = 0;
15283dec9fcdSqs 
15293dec9fcdSqs 		status = hxge_alloc_rx_buf_dma(hxgep, st_rdc, &dma_buf_p[i],
15303dec9fcdSqs 		    rx_buf_alloc_size, hxgep->rx_default_block_size,
15313dec9fcdSqs 		    &num_chunks[i]);
15323dec9fcdSqs 		if (status != HXGE_OK) {
15333dec9fcdSqs 			break;
15343dec9fcdSqs 		}
15353dec9fcdSqs 
15363dec9fcdSqs 		st_rdc++;
15373dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
15383dec9fcdSqs 		    " hxge_alloc_rx_mem_pool DONE  alloc mem: "
15393dec9fcdSqs 		    "dma %d dma_buf_p %llx &dma_buf_p %llx", i,
15403dec9fcdSqs 		    dma_buf_p[i], &dma_buf_p[i]));
15413dec9fcdSqs 	}
15423dec9fcdSqs 
15433dec9fcdSqs 	if (i < ndmas) {
15443dec9fcdSqs 		goto hxge_alloc_rx_mem_fail1;
15453dec9fcdSqs 	}
15463dec9fcdSqs 
15473dec9fcdSqs 	/*
15483dec9fcdSqs 	 * Allocate memory for descriptor rings and mailbox.
15493dec9fcdSqs 	 */
15503dec9fcdSqs 	st_rdc = p_cfgp->start_rdc;
15513dec9fcdSqs 	for (j = 0; j < ndmas; j++) {
15523dec9fcdSqs 		status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc, &dma_cntl_p[j],
15533dec9fcdSqs 		    rx_cntl_alloc_size);
15543dec9fcdSqs 		if (status != HXGE_OK) {
15553dec9fcdSqs 			break;
15563dec9fcdSqs 		}
15573dec9fcdSqs 		st_rdc++;
15583dec9fcdSqs 	}
15593dec9fcdSqs 
15603dec9fcdSqs 	if (j < ndmas) {
15613dec9fcdSqs 		goto hxge_alloc_rx_mem_fail2;
15623dec9fcdSqs 	}
15633dec9fcdSqs 
15643dec9fcdSqs 	dma_poolp->ndmas = ndmas;
15653dec9fcdSqs 	dma_poolp->num_chunks = num_chunks;
15663dec9fcdSqs 	dma_poolp->buf_allocated = B_TRUE;
15673dec9fcdSqs 	hxgep->rx_buf_pool_p = dma_poolp;
15683dec9fcdSqs 	dma_poolp->dma_buf_pool_p = dma_buf_p;
15693dec9fcdSqs 
15703dec9fcdSqs 	dma_cntl_poolp->ndmas = ndmas;
15713dec9fcdSqs 	dma_cntl_poolp->buf_allocated = B_TRUE;
15723dec9fcdSqs 	hxgep->rx_cntl_pool_p = dma_cntl_poolp;
15733dec9fcdSqs 	dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
15743dec9fcdSqs 
15753dec9fcdSqs 	goto hxge_alloc_rx_mem_pool_exit;
15763dec9fcdSqs 
15773dec9fcdSqs hxge_alloc_rx_mem_fail2:
15783dec9fcdSqs 	/* Free control buffers */
15793dec9fcdSqs 	j--;
15803dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
15813dec9fcdSqs 	    "==> hxge_alloc_rx_mem_pool: freeing control bufs (%d)", j));
15823dec9fcdSqs 	for (; j >= 0; j--) {
15833dec9fcdSqs 		hxge_free_rx_cntl_dma(hxgep,
15843dec9fcdSqs 		    (p_hxge_dma_common_t)dma_cntl_p[j]);
15853dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
15863dec9fcdSqs 		    "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
15873dec9fcdSqs 	}
15883dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
15893dec9fcdSqs 	    "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
15903dec9fcdSqs 
15913dec9fcdSqs hxge_alloc_rx_mem_fail1:
15923dec9fcdSqs 	/* Free data buffers */
15933dec9fcdSqs 	i--;
15943dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
15953dec9fcdSqs 	    "==> hxge_alloc_rx_mem_pool: freeing data bufs (%d)", i));
15963dec9fcdSqs 	for (; i >= 0; i--) {
15973dec9fcdSqs 		hxge_free_rx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i],
15983dec9fcdSqs 		    num_chunks[i]);
15993dec9fcdSqs 	}
16003dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16013dec9fcdSqs 	    "==> hxge_alloc_rx_mem_pool: data bufs freed (%d)", i));
16023dec9fcdSqs 
16033dec9fcdSqs 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
16043dec9fcdSqs 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
16053dec9fcdSqs 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
16063dec9fcdSqs 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
16073dec9fcdSqs 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
16083dec9fcdSqs 
16093dec9fcdSqs hxge_alloc_rx_mem_pool_exit:
16103dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
16113dec9fcdSqs 	    "<== hxge_alloc_rx_mem_pool:status 0x%08x", status));
16123dec9fcdSqs 
16133dec9fcdSqs 	return (status);
16143dec9fcdSqs }
16153dec9fcdSqs 
16163dec9fcdSqs static void
16173dec9fcdSqs hxge_free_rx_mem_pool(p_hxge_t hxgep)
16183dec9fcdSqs {
16193dec9fcdSqs 	uint32_t		i, ndmas;
16203dec9fcdSqs 	p_hxge_dma_pool_t	dma_poolp;
16213dec9fcdSqs 	p_hxge_dma_common_t	*dma_buf_p;
16223dec9fcdSqs 	p_hxge_dma_pool_t	dma_cntl_poolp;
16233dec9fcdSqs 	p_hxge_dma_common_t	*dma_cntl_p;
16243dec9fcdSqs 	uint32_t		*num_chunks;
16253dec9fcdSqs 
16263dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_free_rx_mem_pool"));
16273dec9fcdSqs 
16283dec9fcdSqs 	dma_poolp = hxgep->rx_buf_pool_p;
16293dec9fcdSqs 	if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
16303dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool "
16313dec9fcdSqs 		    "(null rx buf pool or buf not allocated"));
16323dec9fcdSqs 		return;
16333dec9fcdSqs 	}
16343dec9fcdSqs 
16353dec9fcdSqs 	dma_cntl_poolp = hxgep->rx_cntl_pool_p;
16363dec9fcdSqs 	if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
16373dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
16383dec9fcdSqs 		    "<== hxge_free_rx_mem_pool "
16393dec9fcdSqs 		    "(null rx cntl buf pool or cntl buf not allocated"));
16403dec9fcdSqs 		return;
16413dec9fcdSqs 	}
16423dec9fcdSqs 
16433dec9fcdSqs 	dma_buf_p = dma_poolp->dma_buf_pool_p;
16443dec9fcdSqs 	num_chunks = dma_poolp->num_chunks;
16453dec9fcdSqs 
16463dec9fcdSqs 	dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
16473dec9fcdSqs 	ndmas = dma_cntl_poolp->ndmas;
16483dec9fcdSqs 
16493dec9fcdSqs 	for (i = 0; i < ndmas; i++) {
16503dec9fcdSqs 		hxge_free_rx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]);
16513dec9fcdSqs 	}
16523dec9fcdSqs 
16533dec9fcdSqs 	for (i = 0; i < ndmas; i++) {
16543dec9fcdSqs 		hxge_free_rx_cntl_dma(hxgep, dma_cntl_p[i]);
16553dec9fcdSqs 	}
16563dec9fcdSqs 
16573dec9fcdSqs 	for (i = 0; i < ndmas; i++) {
16583dec9fcdSqs 		KMEM_FREE(dma_buf_p[i],
16593dec9fcdSqs 		    sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
16603dec9fcdSqs 		KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t));
16613dec9fcdSqs 	}
16623dec9fcdSqs 
16633dec9fcdSqs 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
16643dec9fcdSqs 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
16653dec9fcdSqs 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
16663dec9fcdSqs 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
16673dec9fcdSqs 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
16683dec9fcdSqs 
16693dec9fcdSqs 	hxgep->rx_buf_pool_p = NULL;
16703dec9fcdSqs 	hxgep->rx_cntl_pool_p = NULL;
16713dec9fcdSqs 
16723dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool"));
16733dec9fcdSqs }
16743dec9fcdSqs 
16753dec9fcdSqs static hxge_status_t
16763dec9fcdSqs hxge_alloc_rx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel,
16773dec9fcdSqs     p_hxge_dma_common_t *dmap,
16783dec9fcdSqs     size_t alloc_size, size_t block_size, uint32_t *num_chunks)
16793dec9fcdSqs {
16803dec9fcdSqs 	p_hxge_dma_common_t	rx_dmap;
16813dec9fcdSqs 	hxge_status_t		status = HXGE_OK;
16823dec9fcdSqs 	size_t			total_alloc_size;
16833dec9fcdSqs 	size_t			allocated = 0;
16843dec9fcdSqs 	int			i, size_index, array_size;
16853dec9fcdSqs 
16863dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_buf_dma"));
16873dec9fcdSqs 
16883dec9fcdSqs 	rx_dmap = (p_hxge_dma_common_t)
16893dec9fcdSqs 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP);
16903dec9fcdSqs 
16913dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
16923dec9fcdSqs 	    " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ",
16933dec9fcdSqs 	    dma_channel, alloc_size, block_size, dmap));
16943dec9fcdSqs 
16953dec9fcdSqs 	total_alloc_size = alloc_size;
16963dec9fcdSqs 
16973dec9fcdSqs 	i = 0;
16983dec9fcdSqs 	size_index = 0;
16993dec9fcdSqs 	array_size = sizeof (alloc_sizes) / sizeof (size_t);
17003dec9fcdSqs 	while ((alloc_sizes[size_index] < alloc_size) &&
17013dec9fcdSqs 	    (size_index < array_size))
17023dec9fcdSqs 		size_index++;
17033dec9fcdSqs 	if (size_index >= array_size) {
17043dec9fcdSqs 		size_index = array_size - 1;
17053dec9fcdSqs 	}
17063dec9fcdSqs 
17073dec9fcdSqs 	while ((allocated < total_alloc_size) &&
17083dec9fcdSqs 	    (size_index >= 0) && (i < HXGE_DMA_BLOCK)) {
17093dec9fcdSqs 		rx_dmap[i].dma_chunk_index = i;
17103dec9fcdSqs 		rx_dmap[i].block_size = block_size;
17113dec9fcdSqs 		rx_dmap[i].alength = alloc_sizes[size_index];
17123dec9fcdSqs 		rx_dmap[i].orig_alength = rx_dmap[i].alength;
17133dec9fcdSqs 		rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
17143dec9fcdSqs 		rx_dmap[i].dma_channel = dma_channel;
17153dec9fcdSqs 		rx_dmap[i].contig_alloc_type = B_FALSE;
17163dec9fcdSqs 
17173dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
17183dec9fcdSqs 		    "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x "
17193dec9fcdSqs 		    "i %d nblocks %d alength %d",
17203dec9fcdSqs 		    dma_channel, i, &rx_dmap[i], block_size,
17213dec9fcdSqs 		    i, rx_dmap[i].nblocks, rx_dmap[i].alength));
17223dec9fcdSqs 		status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
17233dec9fcdSqs 		    &hxge_rx_dma_attr, rx_dmap[i].alength,
17243dec9fcdSqs 		    &hxge_dev_buf_dma_acc_attr,
17253dec9fcdSqs 		    DDI_DMA_READ | DDI_DMA_STREAMING,
17263dec9fcdSqs 		    (p_hxge_dma_common_t)(&rx_dmap[i]));
17273dec9fcdSqs 		if (status != HXGE_OK) {
17283dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
17293dec9fcdSqs 			    " hxge_alloc_rx_buf_dma: Alloc Failed: "
17303dec9fcdSqs 			    " for size: %d", alloc_sizes[size_index]));
17313dec9fcdSqs 			size_index--;
17323dec9fcdSqs 		} else {
17333dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
17343dec9fcdSqs 			    " alloc_rx_buf_dma allocated rdc %d "
17353dec9fcdSqs 			    "chunk %d size %x dvma %x bufp %llx ",
17363dec9fcdSqs 			    dma_channel, i, rx_dmap[i].alength,
17373dec9fcdSqs 			    rx_dmap[i].ioaddr_pp, &rx_dmap[i]));
17383dec9fcdSqs 			i++;
17393dec9fcdSqs 			allocated += alloc_sizes[size_index];
17403dec9fcdSqs 		}
17413dec9fcdSqs 	}
17423dec9fcdSqs 
17433dec9fcdSqs 	if (allocated < total_alloc_size) {
17443dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
17453dec9fcdSqs 		    " hxge_alloc_rx_buf_dma failed due to"
17463dec9fcdSqs 		    " allocated(%d) < required(%d)",
17473dec9fcdSqs 		    allocated, total_alloc_size));
17483dec9fcdSqs 		goto hxge_alloc_rx_mem_fail1;
17493dec9fcdSqs 	}
17503dec9fcdSqs 
17513dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
17523dec9fcdSqs 	    " alloc_rx_buf_dma rdc %d allocated %d chunks", dma_channel, i));
17533dec9fcdSqs 
17543dec9fcdSqs 	*num_chunks = i;
17553dec9fcdSqs 	*dmap = rx_dmap;
17563dec9fcdSqs 
17573dec9fcdSqs 	goto hxge_alloc_rx_mem_exit;
17583dec9fcdSqs 
17593dec9fcdSqs hxge_alloc_rx_mem_fail1:
17603dec9fcdSqs 	KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
17613dec9fcdSqs 
17623dec9fcdSqs hxge_alloc_rx_mem_exit:
17633dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
17643dec9fcdSqs 	    "<== hxge_alloc_rx_buf_dma status 0x%08x", status));
17653dec9fcdSqs 
17663dec9fcdSqs 	return (status);
17673dec9fcdSqs }
17683dec9fcdSqs 
17693dec9fcdSqs /*ARGSUSED*/
17703dec9fcdSqs static void
17713dec9fcdSqs hxge_free_rx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap,
17723dec9fcdSqs     uint32_t num_chunks)
17733dec9fcdSqs {
17743dec9fcdSqs 	int i;
17753dec9fcdSqs 
17763dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
17773dec9fcdSqs 	    "==> hxge_free_rx_buf_dma: # of chunks %d", num_chunks));
17783dec9fcdSqs 
17793dec9fcdSqs 	for (i = 0; i < num_chunks; i++) {
17803dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
17813dec9fcdSqs 		    "==> hxge_free_rx_buf_dma: chunk %d dmap 0x%llx", i, dmap));
17823dec9fcdSqs 		hxge_dma_mem_free(dmap++);
17833dec9fcdSqs 	}
17843dec9fcdSqs 
17853dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_buf_dma"));
17863dec9fcdSqs }
17873dec9fcdSqs 
17883dec9fcdSqs /*ARGSUSED*/
17893dec9fcdSqs static hxge_status_t
17903dec9fcdSqs hxge_alloc_rx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel,
17913dec9fcdSqs     p_hxge_dma_common_t *dmap, size_t size)
17923dec9fcdSqs {
17933dec9fcdSqs 	p_hxge_dma_common_t	rx_dmap;
17943dec9fcdSqs 	hxge_status_t		status = HXGE_OK;
17953dec9fcdSqs 
17963dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_cntl_dma"));
17973dec9fcdSqs 
17983dec9fcdSqs 	rx_dmap = (p_hxge_dma_common_t)
17993dec9fcdSqs 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t), KM_SLEEP);
18003dec9fcdSqs 
18013dec9fcdSqs 	rx_dmap->contig_alloc_type = B_FALSE;
18023dec9fcdSqs 
18033dec9fcdSqs 	status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
18043dec9fcdSqs 	    &hxge_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr,
18053dec9fcdSqs 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, rx_dmap);
18063dec9fcdSqs 	if (status != HXGE_OK) {
18073dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
18083dec9fcdSqs 		    " hxge_alloc_rx_cntl_dma: Alloc Failed: "
18093dec9fcdSqs 		    " for size: %d", size));
18103dec9fcdSqs 		goto hxge_alloc_rx_cntl_dma_fail1;
18113dec9fcdSqs 	}
18123dec9fcdSqs 
18133dec9fcdSqs 	*dmap = rx_dmap;
18143dec9fcdSqs 
18153dec9fcdSqs 	goto hxge_alloc_rx_cntl_dma_exit;
18163dec9fcdSqs 
18173dec9fcdSqs hxge_alloc_rx_cntl_dma_fail1:
18183dec9fcdSqs 	KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t));
18193dec9fcdSqs 
18203dec9fcdSqs hxge_alloc_rx_cntl_dma_exit:
18213dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
18223dec9fcdSqs 	    "<== hxge_alloc_rx_cntl_dma status 0x%08x", status));
18233dec9fcdSqs 
18243dec9fcdSqs 	return (status);
18253dec9fcdSqs }
18263dec9fcdSqs 
18273dec9fcdSqs /*ARGSUSED*/
18283dec9fcdSqs static void
18293dec9fcdSqs hxge_free_rx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap)
18303dec9fcdSqs {
18313dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_rx_cntl_dma"));
18323dec9fcdSqs 
18333dec9fcdSqs 	hxge_dma_mem_free(dmap);
18343dec9fcdSqs 
18353dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_rx_cntl_dma"));
18363dec9fcdSqs }
18373dec9fcdSqs 
18383dec9fcdSqs static hxge_status_t
18393dec9fcdSqs hxge_alloc_tx_mem_pool(p_hxge_t hxgep)
18403dec9fcdSqs {
18413dec9fcdSqs 	hxge_status_t		status = HXGE_OK;
18423dec9fcdSqs 	int			i, j;
18433dec9fcdSqs 	uint32_t		ndmas, st_tdc;
18443dec9fcdSqs 	p_hxge_dma_pt_cfg_t	p_all_cfgp;
18453dec9fcdSqs 	p_hxge_hw_pt_cfg_t	p_cfgp;
18463dec9fcdSqs 	p_hxge_dma_pool_t	dma_poolp;
18473dec9fcdSqs 	p_hxge_dma_common_t	*dma_buf_p;
18483dec9fcdSqs 	p_hxge_dma_pool_t	dma_cntl_poolp;
18493dec9fcdSqs 	p_hxge_dma_common_t	*dma_cntl_p;
18503dec9fcdSqs 	size_t			tx_buf_alloc_size;
18513dec9fcdSqs 	size_t			tx_cntl_alloc_size;
18523dec9fcdSqs 	uint32_t		*num_chunks;	/* per dma */
18533dec9fcdSqs 
18543dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool"));
18553dec9fcdSqs 
18563dec9fcdSqs 	p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
18573dec9fcdSqs 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
18583dec9fcdSqs 	st_tdc = p_cfgp->start_tdc;
18593dec9fcdSqs 	ndmas = p_cfgp->max_tdcs;
18603dec9fcdSqs 
18613dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool: "
18623dec9fcdSqs 	    "p_cfgp 0x%016llx start_tdc %d ndmas %d hxgep->max_tdcs %d",
18633dec9fcdSqs 	    p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, hxgep->max_tdcs));
18643dec9fcdSqs 	/*
18653dec9fcdSqs 	 * Allocate memory for each transmit DMA channel.
18663dec9fcdSqs 	 */
18673dec9fcdSqs 	dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t),
18683dec9fcdSqs 	    KM_SLEEP);
18693dec9fcdSqs 	dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
18703dec9fcdSqs 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
18713dec9fcdSqs 
18723dec9fcdSqs 	dma_cntl_poolp = (p_hxge_dma_pool_t)
18733dec9fcdSqs 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
18743dec9fcdSqs 	dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
18753dec9fcdSqs 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
18763dec9fcdSqs 
18773dec9fcdSqs 	hxgep->hxge_port_tx_ring_size = hxge_tx_ring_size;
18783dec9fcdSqs 
18793dec9fcdSqs 	/*
18803dec9fcdSqs 	 * Assume that each DMA channel will be configured with default
18813dec9fcdSqs 	 * transmit bufer size for copying transmit data. (For packet payload
18823dec9fcdSqs 	 * over this limit, packets will not be copied.)
18833dec9fcdSqs 	 */
18843dec9fcdSqs 	tx_buf_alloc_size = (hxge_bcopy_thresh * hxge_tx_ring_size);
18853dec9fcdSqs 
18863dec9fcdSqs 	/*
18873dec9fcdSqs 	 * Addresses of transmit descriptor ring and the mailbox must be all
18883dec9fcdSqs 	 * cache-aligned (64 bytes).
18893dec9fcdSqs 	 */
18903dec9fcdSqs 	tx_cntl_alloc_size = hxge_tx_ring_size;
18913dec9fcdSqs 	tx_cntl_alloc_size *= (sizeof (tx_desc_t));
18923dec9fcdSqs 	tx_cntl_alloc_size += sizeof (txdma_mailbox_t);
18933dec9fcdSqs 
18943dec9fcdSqs 	num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas,
18953dec9fcdSqs 	    KM_SLEEP);
18963dec9fcdSqs 
18973dec9fcdSqs 	/*
18983dec9fcdSqs 	 * Allocate memory for transmit buffers and descriptor rings. Replace
18993dec9fcdSqs 	 * allocation functions with interface functions provided by the
19003dec9fcdSqs 	 * partition manager when it is available.
19013dec9fcdSqs 	 *
19023dec9fcdSqs 	 * Allocate memory for the transmit buffer pool.
19033dec9fcdSqs 	 */
19043dec9fcdSqs 	for (i = 0; i < ndmas; i++) {
19053dec9fcdSqs 		num_chunks[i] = 0;
19063dec9fcdSqs 		status = hxge_alloc_tx_buf_dma(hxgep, st_tdc, &dma_buf_p[i],
19073dec9fcdSqs 		    tx_buf_alloc_size, hxge_bcopy_thresh, &num_chunks[i]);
19083dec9fcdSqs 		if (status != HXGE_OK) {
19093dec9fcdSqs 			break;
19103dec9fcdSqs 		}
19113dec9fcdSqs 		st_tdc++;
19123dec9fcdSqs 	}
19133dec9fcdSqs 
19143dec9fcdSqs 	if (i < ndmas) {
19153dec9fcdSqs 		goto hxge_alloc_tx_mem_pool_fail1;
19163dec9fcdSqs 	}
19173dec9fcdSqs 
19183dec9fcdSqs 	st_tdc = p_cfgp->start_tdc;
19193dec9fcdSqs 
19203dec9fcdSqs 	/*
19213dec9fcdSqs 	 * Allocate memory for descriptor rings and mailbox.
19223dec9fcdSqs 	 */
19233dec9fcdSqs 	for (j = 0; j < ndmas; j++) {
19243dec9fcdSqs 		status = hxge_alloc_tx_cntl_dma(hxgep, st_tdc, &dma_cntl_p[j],
19253dec9fcdSqs 		    tx_cntl_alloc_size);
19263dec9fcdSqs 		if (status != HXGE_OK) {
19273dec9fcdSqs 			break;
19283dec9fcdSqs 		}
19293dec9fcdSqs 		st_tdc++;
19303dec9fcdSqs 	}
19313dec9fcdSqs 
19323dec9fcdSqs 	if (j < ndmas) {
19333dec9fcdSqs 		goto hxge_alloc_tx_mem_pool_fail2;
19343dec9fcdSqs 	}
19353dec9fcdSqs 
19363dec9fcdSqs 	dma_poolp->ndmas = ndmas;
19373dec9fcdSqs 	dma_poolp->num_chunks = num_chunks;
19383dec9fcdSqs 	dma_poolp->buf_allocated = B_TRUE;
19393dec9fcdSqs 	dma_poolp->dma_buf_pool_p = dma_buf_p;
19403dec9fcdSqs 	hxgep->tx_buf_pool_p = dma_poolp;
19413dec9fcdSqs 
19423dec9fcdSqs 	dma_cntl_poolp->ndmas = ndmas;
19433dec9fcdSqs 	dma_cntl_poolp->buf_allocated = B_TRUE;
19443dec9fcdSqs 	dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
19453dec9fcdSqs 	hxgep->tx_cntl_pool_p = dma_cntl_poolp;
19463dec9fcdSqs 
19473dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM_CTL,
19483dec9fcdSqs 	    "==> hxge_alloc_tx_mem_pool: start_tdc %d "
19493dec9fcdSqs 	    "ndmas %d poolp->ndmas %d", st_tdc, ndmas, dma_poolp->ndmas));
19503dec9fcdSqs 
19513dec9fcdSqs 	goto hxge_alloc_tx_mem_pool_exit;
19523dec9fcdSqs 
19533dec9fcdSqs hxge_alloc_tx_mem_pool_fail2:
19543dec9fcdSqs 	/* Free control buffers */
19553dec9fcdSqs 	j--;
19563dec9fcdSqs 	for (; j >= 0; j--) {
19573dec9fcdSqs 		hxge_free_tx_cntl_dma(hxgep,
19583dec9fcdSqs 		    (p_hxge_dma_common_t)dma_cntl_p[j]);
19593dec9fcdSqs 	}
19603dec9fcdSqs 
19613dec9fcdSqs hxge_alloc_tx_mem_pool_fail1:
19623dec9fcdSqs 	/* Free data buffers */
19633dec9fcdSqs 	i--;
19643dec9fcdSqs 	for (; i >= 0; i--) {
19653dec9fcdSqs 		hxge_free_tx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i],
19663dec9fcdSqs 		    num_chunks[i]);
19673dec9fcdSqs 	}
19683dec9fcdSqs 
19693dec9fcdSqs 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
19703dec9fcdSqs 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
19713dec9fcdSqs 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
19723dec9fcdSqs 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
19733dec9fcdSqs 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
19743dec9fcdSqs 
19753dec9fcdSqs hxge_alloc_tx_mem_pool_exit:
19763dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM_CTL,
19773dec9fcdSqs 	    "<== hxge_alloc_tx_mem_pool:status 0x%08x", status));
19783dec9fcdSqs 
19793dec9fcdSqs 	return (status);
19803dec9fcdSqs }
19813dec9fcdSqs 
19823dec9fcdSqs static hxge_status_t
19833dec9fcdSqs hxge_alloc_tx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel,
19843dec9fcdSqs     p_hxge_dma_common_t *dmap, size_t alloc_size,
19853dec9fcdSqs     size_t block_size, uint32_t *num_chunks)
19863dec9fcdSqs {
19873dec9fcdSqs 	p_hxge_dma_common_t	tx_dmap;
19883dec9fcdSqs 	hxge_status_t		status = HXGE_OK;
19893dec9fcdSqs 	size_t			total_alloc_size;
19903dec9fcdSqs 	size_t			allocated = 0;
19913dec9fcdSqs 	int			i, size_index, array_size;
19923dec9fcdSqs 
19933dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_buf_dma"));
19943dec9fcdSqs 
19953dec9fcdSqs 	tx_dmap = (p_hxge_dma_common_t)
19963dec9fcdSqs 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP);
19973dec9fcdSqs 
19983dec9fcdSqs 	total_alloc_size = alloc_size;
19993dec9fcdSqs 	i = 0;
20003dec9fcdSqs 	size_index = 0;
20013dec9fcdSqs 	array_size = sizeof (alloc_sizes) / sizeof (size_t);
20023dec9fcdSqs 	while ((alloc_sizes[size_index] < alloc_size) &&
20033dec9fcdSqs 	    (size_index < array_size))
20043dec9fcdSqs 		size_index++;
20053dec9fcdSqs 	if (size_index >= array_size) {
20063dec9fcdSqs 		size_index = array_size - 1;
20073dec9fcdSqs 	}
20083dec9fcdSqs 
20093dec9fcdSqs 	while ((allocated < total_alloc_size) &&
20103dec9fcdSqs 	    (size_index >= 0) && (i < HXGE_DMA_BLOCK)) {
20113dec9fcdSqs 		tx_dmap[i].dma_chunk_index = i;
20123dec9fcdSqs 		tx_dmap[i].block_size = block_size;
20133dec9fcdSqs 		tx_dmap[i].alength = alloc_sizes[size_index];
20143dec9fcdSqs 		tx_dmap[i].orig_alength = tx_dmap[i].alength;
20153dec9fcdSqs 		tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
20163dec9fcdSqs 		tx_dmap[i].dma_channel = dma_channel;
20173dec9fcdSqs 		tx_dmap[i].contig_alloc_type = B_FALSE;
20183dec9fcdSqs 
20193dec9fcdSqs 		status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
20203dec9fcdSqs 		    &hxge_tx_dma_attr, tx_dmap[i].alength,
20213dec9fcdSqs 		    &hxge_dev_buf_dma_acc_attr,
20223dec9fcdSqs 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
20233dec9fcdSqs 		    (p_hxge_dma_common_t)(&tx_dmap[i]));
20243dec9fcdSqs 		if (status != HXGE_OK) {
20253dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
20263dec9fcdSqs 			    " hxge_alloc_tx_buf_dma: Alloc Failed: "
20273dec9fcdSqs 			    " for size: %d", alloc_sizes[size_index]));
20283dec9fcdSqs 			size_index--;
20293dec9fcdSqs 		} else {
20303dec9fcdSqs 			i++;
20313dec9fcdSqs 			allocated += alloc_sizes[size_index];
20323dec9fcdSqs 		}
20333dec9fcdSqs 	}
20343dec9fcdSqs 
20353dec9fcdSqs 	if (allocated < total_alloc_size) {
20363dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
20373dec9fcdSqs 		    " hxge_alloc_tx_buf_dma: failed due to"
20383dec9fcdSqs 		    " allocated(%d) < required(%d)",
20393dec9fcdSqs 		    allocated, total_alloc_size));
20403dec9fcdSqs 		goto hxge_alloc_tx_mem_fail1;
20413dec9fcdSqs 	}
20423dec9fcdSqs 
20433dec9fcdSqs 	*num_chunks = i;
20443dec9fcdSqs 	*dmap = tx_dmap;
20453dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
20463dec9fcdSqs 	    "==> hxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d",
20473dec9fcdSqs 	    *dmap, i));
20483dec9fcdSqs 	goto hxge_alloc_tx_mem_exit;
20493dec9fcdSqs 
20503dec9fcdSqs hxge_alloc_tx_mem_fail1:
20513dec9fcdSqs 	KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
20523dec9fcdSqs 
20533dec9fcdSqs hxge_alloc_tx_mem_exit:
20543dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
20553dec9fcdSqs 	    "<== hxge_alloc_tx_buf_dma status 0x%08x", status));
20563dec9fcdSqs 
20573dec9fcdSqs 	return (status);
20583dec9fcdSqs }
20593dec9fcdSqs 
20603dec9fcdSqs /*ARGSUSED*/
20613dec9fcdSqs static void
20623dec9fcdSqs hxge_free_tx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap,
20633dec9fcdSqs     uint32_t num_chunks)
20643dec9fcdSqs {
20653dec9fcdSqs 	int i;
20663dec9fcdSqs 
20673dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_tx_buf_dma"));
20683dec9fcdSqs 
20693dec9fcdSqs 	for (i = 0; i < num_chunks; i++) {
20703dec9fcdSqs 		hxge_dma_mem_free(dmap++);
20713dec9fcdSqs 	}
20723dec9fcdSqs 
20733dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_tx_buf_dma"));
20743dec9fcdSqs }
20753dec9fcdSqs 
20763dec9fcdSqs /*ARGSUSED*/
20773dec9fcdSqs static hxge_status_t
20783dec9fcdSqs hxge_alloc_tx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel,
20793dec9fcdSqs     p_hxge_dma_common_t *dmap, size_t size)
20803dec9fcdSqs {
20813dec9fcdSqs 	p_hxge_dma_common_t	tx_dmap;
20823dec9fcdSqs 	hxge_status_t		status = HXGE_OK;
20833dec9fcdSqs 
20843dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_cntl_dma"));
20853dec9fcdSqs 
20863dec9fcdSqs 	tx_dmap = (p_hxge_dma_common_t)KMEM_ZALLOC(sizeof (hxge_dma_common_t),
20873dec9fcdSqs 	    KM_SLEEP);
20883dec9fcdSqs 
20893dec9fcdSqs 	tx_dmap->contig_alloc_type = B_FALSE;
20903dec9fcdSqs 
20913dec9fcdSqs 	status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
20923dec9fcdSqs 	    &hxge_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr,
20933dec9fcdSqs 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, tx_dmap);
20943dec9fcdSqs 	if (status != HXGE_OK) {
20953dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
20963dec9fcdSqs 		    " hxge_alloc_tx_cntl_dma: Alloc Failed: "
20973dec9fcdSqs 		    " for size: %d", size));
20983dec9fcdSqs 		goto hxge_alloc_tx_cntl_dma_fail1;
20993dec9fcdSqs 	}
21003dec9fcdSqs 
21013dec9fcdSqs 	*dmap = tx_dmap;
21023dec9fcdSqs 
21033dec9fcdSqs 	goto hxge_alloc_tx_cntl_dma_exit;
21043dec9fcdSqs 
21053dec9fcdSqs hxge_alloc_tx_cntl_dma_fail1:
21063dec9fcdSqs 	KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t));
21073dec9fcdSqs 
21083dec9fcdSqs hxge_alloc_tx_cntl_dma_exit:
21093dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
21103dec9fcdSqs 	    "<== hxge_alloc_tx_cntl_dma status 0x%08x", status));
21113dec9fcdSqs 
21123dec9fcdSqs 	return (status);
21133dec9fcdSqs }
21143dec9fcdSqs 
21153dec9fcdSqs /*ARGSUSED*/
21163dec9fcdSqs static void
21173dec9fcdSqs hxge_free_tx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap)
21183dec9fcdSqs {
21193dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_tx_cntl_dma"));
21203dec9fcdSqs 
21213dec9fcdSqs 	hxge_dma_mem_free(dmap);
21223dec9fcdSqs 
21233dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_tx_cntl_dma"));
21243dec9fcdSqs }
21253dec9fcdSqs 
21263dec9fcdSqs static void
21273dec9fcdSqs hxge_free_tx_mem_pool(p_hxge_t hxgep)
21283dec9fcdSqs {
21293dec9fcdSqs 	uint32_t		i, ndmas;
21303dec9fcdSqs 	p_hxge_dma_pool_t	dma_poolp;
21313dec9fcdSqs 	p_hxge_dma_common_t	*dma_buf_p;
21323dec9fcdSqs 	p_hxge_dma_pool_t	dma_cntl_poolp;
21333dec9fcdSqs 	p_hxge_dma_common_t	*dma_cntl_p;
21343dec9fcdSqs 	uint32_t		*num_chunks;
21353dec9fcdSqs 
21363dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "==> hxge_free_tx_mem_pool"));
21373dec9fcdSqs 
21383dec9fcdSqs 	dma_poolp = hxgep->tx_buf_pool_p;
21393dec9fcdSqs 	if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
21403dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MEM3_CTL,
21413dec9fcdSqs 		    "<== hxge_free_tx_mem_pool "
21423dec9fcdSqs 		    "(null rx buf pool or buf not allocated"));
21433dec9fcdSqs 		return;
21443dec9fcdSqs 	}
21453dec9fcdSqs 
21463dec9fcdSqs 	dma_cntl_poolp = hxgep->tx_cntl_pool_p;
21473dec9fcdSqs 	if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
21483dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MEM3_CTL,
21493dec9fcdSqs 		    "<== hxge_free_tx_mem_pool "
21503dec9fcdSqs 		    "(null tx cntl buf pool or cntl buf not allocated"));
21513dec9fcdSqs 		return;
21523dec9fcdSqs 	}
21533dec9fcdSqs 
21543dec9fcdSqs 	dma_buf_p = dma_poolp->dma_buf_pool_p;
21553dec9fcdSqs 	num_chunks = dma_poolp->num_chunks;
21563dec9fcdSqs 
21573dec9fcdSqs 	dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
21583dec9fcdSqs 	ndmas = dma_cntl_poolp->ndmas;
21593dec9fcdSqs 
21603dec9fcdSqs 	for (i = 0; i < ndmas; i++) {
21613dec9fcdSqs 		hxge_free_tx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]);
21623dec9fcdSqs 	}
21633dec9fcdSqs 
21643dec9fcdSqs 	for (i = 0; i < ndmas; i++) {
21653dec9fcdSqs 		hxge_free_tx_cntl_dma(hxgep, dma_cntl_p[i]);
21663dec9fcdSqs 	}
21673dec9fcdSqs 
21683dec9fcdSqs 	for (i = 0; i < ndmas; i++) {
21693dec9fcdSqs 		KMEM_FREE(dma_buf_p[i],
21703dec9fcdSqs 		    sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
21713dec9fcdSqs 		KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t));
21723dec9fcdSqs 	}
21733dec9fcdSqs 
21743dec9fcdSqs 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
21753dec9fcdSqs 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
21763dec9fcdSqs 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
21773dec9fcdSqs 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
21783dec9fcdSqs 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
21793dec9fcdSqs 
21803dec9fcdSqs 	hxgep->tx_buf_pool_p = NULL;
21813dec9fcdSqs 	hxgep->tx_cntl_pool_p = NULL;
21823dec9fcdSqs 
21833dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "<== hxge_free_tx_mem_pool"));
21843dec9fcdSqs }
21853dec9fcdSqs 
21863dec9fcdSqs /*ARGSUSED*/
21873dec9fcdSqs static hxge_status_t
21883dec9fcdSqs hxge_dma_mem_alloc(p_hxge_t hxgep, dma_method_t method,
21893dec9fcdSqs     struct ddi_dma_attr *dma_attrp,
21903dec9fcdSqs     size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags,
21913dec9fcdSqs     p_hxge_dma_common_t dma_p)
21923dec9fcdSqs {
21933dec9fcdSqs 	caddr_t		kaddrp;
21943dec9fcdSqs 	int		ddi_status = DDI_SUCCESS;
21953dec9fcdSqs 
21963dec9fcdSqs 	dma_p->dma_handle = NULL;
21973dec9fcdSqs 	dma_p->acc_handle = NULL;
21983dec9fcdSqs 	dma_p->kaddrp = NULL;
21993dec9fcdSqs 
22003dec9fcdSqs 	ddi_status = ddi_dma_alloc_handle(hxgep->dip, dma_attrp,
22013dec9fcdSqs 	    DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle);
22023dec9fcdSqs 	if (ddi_status != DDI_SUCCESS) {
22033dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
22043dec9fcdSqs 		    "hxge_dma_mem_alloc:ddi_dma_alloc_handle failed."));
22053dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
22063dec9fcdSqs 	}
22073dec9fcdSqs 
22083dec9fcdSqs 	ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, acc_attr_p,
22093dec9fcdSqs 	    xfer_flags, DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength,
22103dec9fcdSqs 	    &dma_p->acc_handle);
22113dec9fcdSqs 	if (ddi_status != DDI_SUCCESS) {
22123dec9fcdSqs 		/* The caller will decide whether it is fatal */
22133dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
22143dec9fcdSqs 		    "hxge_dma_mem_alloc:ddi_dma_mem_alloc failed"));
22153dec9fcdSqs 		ddi_dma_free_handle(&dma_p->dma_handle);
22163dec9fcdSqs 		dma_p->dma_handle = NULL;
22173dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
22183dec9fcdSqs 	}
22193dec9fcdSqs 
22203dec9fcdSqs 	if (dma_p->alength < length) {
22213dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
22223dec9fcdSqs 		    "hxge_dma_mem_alloc:ddi_dma_mem_alloc < length."));
22233dec9fcdSqs 		ddi_dma_mem_free(&dma_p->acc_handle);
22243dec9fcdSqs 		ddi_dma_free_handle(&dma_p->dma_handle);
22253dec9fcdSqs 		dma_p->acc_handle = NULL;
22263dec9fcdSqs 		dma_p->dma_handle = NULL;
22273dec9fcdSqs 		return (HXGE_ERROR);
22283dec9fcdSqs 	}
22293dec9fcdSqs 
22303dec9fcdSqs 	ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
22313dec9fcdSqs 	    kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
22323dec9fcdSqs 	    &dma_p->dma_cookie, &dma_p->ncookies);
22333dec9fcdSqs 	if (ddi_status != DDI_DMA_MAPPED) {
22343dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
22353dec9fcdSqs 		    "hxge_dma_mem_alloc:di_dma_addr_bind failed "
22363dec9fcdSqs 		    "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies));
22373dec9fcdSqs 		if (dma_p->acc_handle) {
22383dec9fcdSqs 			ddi_dma_mem_free(&dma_p->acc_handle);
22393dec9fcdSqs 			dma_p->acc_handle = NULL;
22403dec9fcdSqs 		}
22413dec9fcdSqs 		ddi_dma_free_handle(&dma_p->dma_handle);
22423dec9fcdSqs 		dma_p->dma_handle = NULL;
22433dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
22443dec9fcdSqs 	}
22453dec9fcdSqs 
22463dec9fcdSqs 	if (dma_p->ncookies != 1) {
22473dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
22483dec9fcdSqs 		    "hxge_dma_mem_alloc:ddi_dma_addr_bind > 1 cookie"
22493dec9fcdSqs 		    "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies));
22503dec9fcdSqs 		if (dma_p->acc_handle) {
22513dec9fcdSqs 			ddi_dma_mem_free(&dma_p->acc_handle);
22523dec9fcdSqs 			dma_p->acc_handle = NULL;
22533dec9fcdSqs 		}
22543dec9fcdSqs 		(void) ddi_dma_unbind_handle(dma_p->dma_handle);
22553dec9fcdSqs 		ddi_dma_free_handle(&dma_p->dma_handle);
22563dec9fcdSqs 		dma_p->dma_handle = NULL;
22573dec9fcdSqs 		return (HXGE_ERROR);
22583dec9fcdSqs 	}
22593dec9fcdSqs 
22603dec9fcdSqs 	dma_p->kaddrp = kaddrp;
22613dec9fcdSqs #if defined(__i386)
22623dec9fcdSqs 	dma_p->ioaddr_pp =
22633dec9fcdSqs 	    (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress;
22643dec9fcdSqs #else
22653dec9fcdSqs 	dma_p->ioaddr_pp = (unsigned char *) dma_p->dma_cookie.dmac_laddress;
22663dec9fcdSqs #endif
22673dec9fcdSqs 
22683dec9fcdSqs 	HPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle);
22693dec9fcdSqs 
22703dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_dma_mem_alloc: "
22713dec9fcdSqs 	    "dma buffer allocated: dma_p $%p "
22723dec9fcdSqs 	    "return dmac_ladress from cookie $%p dmac_size %d "
22733dec9fcdSqs 	    "dma_p->ioaddr_p $%p "
22743dec9fcdSqs 	    "dma_p->orig_ioaddr_p $%p "
22753dec9fcdSqs 	    "orig_vatopa $%p "
22763dec9fcdSqs 	    "alength %d (0x%x) "
22773dec9fcdSqs 	    "kaddrp $%p "
22783dec9fcdSqs 	    "length %d (0x%x)",
22793dec9fcdSqs 	    dma_p,
22803dec9fcdSqs 	    dma_p->dma_cookie.dmac_laddress,
22813dec9fcdSqs 	    dma_p->dma_cookie.dmac_size,
22823dec9fcdSqs 	    dma_p->ioaddr_pp,
22833dec9fcdSqs 	    dma_p->orig_ioaddr_pp,
22843dec9fcdSqs 	    dma_p->orig_vatopa,
22853dec9fcdSqs 	    dma_p->alength, dma_p->alength,
22863dec9fcdSqs 	    kaddrp,
22873dec9fcdSqs 	    length, length));
22883dec9fcdSqs 
22893dec9fcdSqs 	return (HXGE_OK);
22903dec9fcdSqs }
22913dec9fcdSqs 
22923dec9fcdSqs static void
22933dec9fcdSqs hxge_dma_mem_free(p_hxge_dma_common_t dma_p)
22943dec9fcdSqs {
22953dec9fcdSqs 	if (dma_p->dma_handle != NULL) {
22963dec9fcdSqs 		if (dma_p->ncookies) {
22973dec9fcdSqs 			(void) ddi_dma_unbind_handle(dma_p->dma_handle);
22983dec9fcdSqs 			dma_p->ncookies = 0;
22993dec9fcdSqs 		}
23003dec9fcdSqs 		ddi_dma_free_handle(&dma_p->dma_handle);
23013dec9fcdSqs 		dma_p->dma_handle = NULL;
23023dec9fcdSqs 	}
23033dec9fcdSqs 	if (dma_p->acc_handle != NULL) {
23043dec9fcdSqs 		ddi_dma_mem_free(&dma_p->acc_handle);
23053dec9fcdSqs 		dma_p->acc_handle = NULL;
23063dec9fcdSqs 		HPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
23073dec9fcdSqs 	}
23083dec9fcdSqs 	dma_p->kaddrp = NULL;
23093dec9fcdSqs 	dma_p->alength = NULL;
23103dec9fcdSqs }
23113dec9fcdSqs 
23123dec9fcdSqs /*
23133dec9fcdSqs  *	hxge_m_start() -- start transmitting and receiving.
23143dec9fcdSqs  *
23153dec9fcdSqs  *	This function is called by the MAC layer when the first
23163dec9fcdSqs  *	stream is open to prepare the hardware ready for sending
23173dec9fcdSqs  *	and transmitting packets.
23183dec9fcdSqs  */
23193dec9fcdSqs static int
23203dec9fcdSqs hxge_m_start(void *arg)
23213dec9fcdSqs {
23223dec9fcdSqs 	p_hxge_t hxgep = (p_hxge_t)arg;
23233dec9fcdSqs 
23243dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_start"));
23253dec9fcdSqs 
23263dec9fcdSqs 	MUTEX_ENTER(hxgep->genlock);
23273dec9fcdSqs 
23283dec9fcdSqs 	if (hxge_init(hxgep) != DDI_SUCCESS) {
23293dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
23303dec9fcdSqs 		    "<== hxge_m_start: initialization failed"));
23313dec9fcdSqs 		MUTEX_EXIT(hxgep->genlock);
23323dec9fcdSqs 		return (EIO);
23333dec9fcdSqs 	}
23343dec9fcdSqs 
23353dec9fcdSqs 	if (hxgep->hxge_mac_state != HXGE_MAC_STARTED) {
23363dec9fcdSqs 		/*
23373dec9fcdSqs 		 * Start timer to check the system error and tx hangs
23383dec9fcdSqs 		 */
23393dec9fcdSqs 		hxgep->hxge_timerid = hxge_start_timer(hxgep,
23403dec9fcdSqs 		    hxge_check_hw_state, HXGE_CHECK_TIMER);
23413dec9fcdSqs 
23423dec9fcdSqs 		hxgep->hxge_mac_state = HXGE_MAC_STARTED;
23433dec9fcdSqs 	}
23443dec9fcdSqs 
23453dec9fcdSqs 	MUTEX_EXIT(hxgep->genlock);
23463dec9fcdSqs 
23473dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_start"));
23483dec9fcdSqs 
23493dec9fcdSqs 	return (0);
23503dec9fcdSqs }
23513dec9fcdSqs 
23523dec9fcdSqs /*
23533dec9fcdSqs  * hxge_m_stop(): stop transmitting and receiving.
23543dec9fcdSqs  */
23553dec9fcdSqs static void
23563dec9fcdSqs hxge_m_stop(void *arg)
23573dec9fcdSqs {
23583dec9fcdSqs 	p_hxge_t hxgep = (p_hxge_t)arg;
23593dec9fcdSqs 
23603dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_stop"));
23613dec9fcdSqs 
23623dec9fcdSqs 	if (hxgep->hxge_timerid) {
23633dec9fcdSqs 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
23643dec9fcdSqs 		hxgep->hxge_timerid = 0;
23653dec9fcdSqs 	}
23663dec9fcdSqs 
23673dec9fcdSqs 	MUTEX_ENTER(hxgep->genlock);
23683dec9fcdSqs 
23693dec9fcdSqs 	hxge_uninit(hxgep);
23703dec9fcdSqs 
23713dec9fcdSqs 	hxgep->hxge_mac_state = HXGE_MAC_STOPPED;
23723dec9fcdSqs 
23733dec9fcdSqs 	MUTEX_EXIT(hxgep->genlock);
23743dec9fcdSqs 
23753dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_stop"));
23763dec9fcdSqs }
23773dec9fcdSqs 
23783dec9fcdSqs static int
23793dec9fcdSqs hxge_m_unicst(void *arg, const uint8_t *macaddr)
23803dec9fcdSqs {
23813dec9fcdSqs 	p_hxge_t		hxgep = (p_hxge_t)arg;
23823dec9fcdSqs 	struct ether_addr	addrp;
23833dec9fcdSqs 	hxge_status_t		status;
23843dec9fcdSqs 
23853dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_unicst"));
23863dec9fcdSqs 
23873dec9fcdSqs 	bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL);
23883dec9fcdSqs 
23893dec9fcdSqs 	status = hxge_set_mac_addr(hxgep, &addrp);
23903dec9fcdSqs 	if (status != HXGE_OK) {
23913dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
23923dec9fcdSqs 		    "<== hxge_m_unicst: set unitcast failed"));
23933dec9fcdSqs 		return (EINVAL);
23943dec9fcdSqs 	}
23953dec9fcdSqs 
23963dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_unicst"));
23973dec9fcdSqs 
23983dec9fcdSqs 	return (0);
23993dec9fcdSqs }
24003dec9fcdSqs 
24013dec9fcdSqs static int
24023dec9fcdSqs hxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
24033dec9fcdSqs {
24043dec9fcdSqs 	p_hxge_t		hxgep = (p_hxge_t)arg;
24053dec9fcdSqs 	struct ether_addr	addrp;
24063dec9fcdSqs 
24073dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_multicst: add %d", add));
24083dec9fcdSqs 
24093dec9fcdSqs 	bcopy(mca, (uint8_t *)&addrp, ETHERADDRL);
24103dec9fcdSqs 
24113dec9fcdSqs 	if (add) {
24123dec9fcdSqs 		if (hxge_add_mcast_addr(hxgep, &addrp)) {
24133dec9fcdSqs 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
24143dec9fcdSqs 			    "<== hxge_m_multicst: add multicast failed"));
24153dec9fcdSqs 			return (EINVAL);
24163dec9fcdSqs 		}
24173dec9fcdSqs 	} else {
24183dec9fcdSqs 		if (hxge_del_mcast_addr(hxgep, &addrp)) {
24193dec9fcdSqs 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
24203dec9fcdSqs 			    "<== hxge_m_multicst: del multicast failed"));
24213dec9fcdSqs 			return (EINVAL);
24223dec9fcdSqs 		}
24233dec9fcdSqs 	}
24243dec9fcdSqs 
24253dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_multicst"));
24263dec9fcdSqs 
24273dec9fcdSqs 	return (0);
24283dec9fcdSqs }
24293dec9fcdSqs 
24303dec9fcdSqs static int
24313dec9fcdSqs hxge_m_promisc(void *arg, boolean_t on)
24323dec9fcdSqs {
24333dec9fcdSqs 	p_hxge_t hxgep = (p_hxge_t)arg;
24343dec9fcdSqs 
24353dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_promisc: on %d", on));
24363dec9fcdSqs 
24373dec9fcdSqs 	if (hxge_set_promisc(hxgep, on)) {
24383dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
24393dec9fcdSqs 		    "<== hxge_m_promisc: set promisc failed"));
24403dec9fcdSqs 		return (EINVAL);
24413dec9fcdSqs 	}
24423dec9fcdSqs 
24433dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_promisc: on %d", on));
24443dec9fcdSqs 
24453dec9fcdSqs 	return (0);
24463dec9fcdSqs }
24473dec9fcdSqs 
24483dec9fcdSqs static void
24493dec9fcdSqs hxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
24503dec9fcdSqs {
24513dec9fcdSqs 	p_hxge_t	hxgep = (p_hxge_t)arg;
24523dec9fcdSqs 	struct iocblk	*iocp = (struct iocblk *)mp->b_rptr;
24533dec9fcdSqs 	boolean_t	need_privilege;
24543dec9fcdSqs 	int		err;
24553dec9fcdSqs 	int		cmd;
24563dec9fcdSqs 
24573dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl"));
24583dec9fcdSqs 
24593dec9fcdSqs 	iocp = (struct iocblk *)mp->b_rptr;
24603dec9fcdSqs 	iocp->ioc_error = 0;
24613dec9fcdSqs 	need_privilege = B_TRUE;
24623dec9fcdSqs 	cmd = iocp->ioc_cmd;
24633dec9fcdSqs 
24643dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl: cmd 0x%08x", cmd));
24653dec9fcdSqs 	switch (cmd) {
24663dec9fcdSqs 	default:
24673dec9fcdSqs 		miocnak(wq, mp, 0, EINVAL);
24683dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl: invalid"));
24693dec9fcdSqs 		return;
24703dec9fcdSqs 
24713dec9fcdSqs 	case LB_GET_INFO_SIZE:
24723dec9fcdSqs 	case LB_GET_INFO:
24733dec9fcdSqs 	case LB_GET_MODE:
24743dec9fcdSqs 		need_privilege = B_FALSE;
24753dec9fcdSqs 		break;
24763dec9fcdSqs 
24773dec9fcdSqs 	case LB_SET_MODE:
24783dec9fcdSqs 		break;
24793dec9fcdSqs 
24803dec9fcdSqs 	case ND_GET:
24813dec9fcdSqs 		need_privilege = B_FALSE;
24823dec9fcdSqs 		break;
24833dec9fcdSqs 	case ND_SET:
24843dec9fcdSqs 		break;
24853dec9fcdSqs 
24863dec9fcdSqs 	case HXGE_GET64:
24873dec9fcdSqs 	case HXGE_PUT64:
24883dec9fcdSqs 	case HXGE_GET_TX_RING_SZ:
24893dec9fcdSqs 	case HXGE_GET_TX_DESC:
24903dec9fcdSqs 	case HXGE_TX_SIDE_RESET:
24913dec9fcdSqs 	case HXGE_RX_SIDE_RESET:
24923dec9fcdSqs 	case HXGE_GLOBAL_RESET:
24933dec9fcdSqs 	case HXGE_RESET_MAC:
24943dec9fcdSqs 	case HXGE_PUT_TCAM:
24953dec9fcdSqs 	case HXGE_GET_TCAM:
24963dec9fcdSqs 	case HXGE_RTRACE:
24973dec9fcdSqs 
24983dec9fcdSqs 		need_privilege = B_FALSE;
24993dec9fcdSqs 		break;
25003dec9fcdSqs 	}
25013dec9fcdSqs 
25023dec9fcdSqs 	if (need_privilege) {
25033dec9fcdSqs 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
25043dec9fcdSqs 		if (err != 0) {
25053dec9fcdSqs 			miocnak(wq, mp, 0, err);
25063dec9fcdSqs 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
25073dec9fcdSqs 			    "<== hxge_m_ioctl: no priv"));
25083dec9fcdSqs 			return;
25093dec9fcdSqs 		}
25103dec9fcdSqs 	}
25113dec9fcdSqs 
25123dec9fcdSqs 	switch (cmd) {
25133dec9fcdSqs 	case ND_GET:
25143dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_GET command"));
25153dec9fcdSqs 	case ND_SET:
25163dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_SET command"));
25173dec9fcdSqs 		hxge_param_ioctl(hxgep, wq, mp, iocp);
25183dec9fcdSqs 		break;
25193dec9fcdSqs 
25203dec9fcdSqs 	case LB_GET_MODE:
25213dec9fcdSqs 	case LB_SET_MODE:
25223dec9fcdSqs 	case LB_GET_INFO_SIZE:
25233dec9fcdSqs 	case LB_GET_INFO:
25243dec9fcdSqs 		hxge_loopback_ioctl(hxgep, wq, mp, iocp);
25253dec9fcdSqs 		break;
25263dec9fcdSqs 
25273dec9fcdSqs 	case HXGE_PUT_TCAM:
25283dec9fcdSqs 	case HXGE_GET_TCAM:
25293dec9fcdSqs 	case HXGE_GET64:
25303dec9fcdSqs 	case HXGE_PUT64:
25313dec9fcdSqs 	case HXGE_GET_TX_RING_SZ:
25323dec9fcdSqs 	case HXGE_GET_TX_DESC:
25333dec9fcdSqs 	case HXGE_TX_SIDE_RESET:
25343dec9fcdSqs 	case HXGE_RX_SIDE_RESET:
25353dec9fcdSqs 	case HXGE_GLOBAL_RESET:
25363dec9fcdSqs 	case HXGE_RESET_MAC:
25373dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL,
25383dec9fcdSqs 		    "==> hxge_m_ioctl: cmd 0x%x", cmd));
25393dec9fcdSqs 		hxge_hw_ioctl(hxgep, wq, mp, iocp);
25403dec9fcdSqs 		break;
25413dec9fcdSqs 	}
25423dec9fcdSqs 
25433dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl"));
25443dec9fcdSqs }
25453dec9fcdSqs 
25463dec9fcdSqs extern void hxge_rx_hw_blank(void *arg, time_t ticks, uint_t count);
25473dec9fcdSqs 
25483dec9fcdSqs static void
25493dec9fcdSqs hxge_m_resources(void *arg)
25503dec9fcdSqs {
25513dec9fcdSqs 	p_hxge_t hxgep = arg;
25523dec9fcdSqs 	mac_rx_fifo_t mrf;
25533dec9fcdSqs 	p_rx_rcr_rings_t rcr_rings;
25543dec9fcdSqs 	p_rx_rcr_ring_t *rcr_p;
25553dec9fcdSqs 	p_rx_rcr_ring_t rcrp;
25563dec9fcdSqs 	uint32_t i, ndmas;
25573dec9fcdSqs 	int status;
25583dec9fcdSqs 
25593dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_m_resources"));
25603dec9fcdSqs 
25613dec9fcdSqs 	MUTEX_ENTER(hxgep->genlock);
25623dec9fcdSqs 
25633dec9fcdSqs 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
25643dec9fcdSqs 		status = hxge_init(hxgep);
25653dec9fcdSqs 		if (status != HXGE_OK) {
25663dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_m_resources: "
25673dec9fcdSqs 			    "hxge_init failed"));
25683dec9fcdSqs 			MUTEX_EXIT(hxgep->genlock);
25693dec9fcdSqs 			return;
25703dec9fcdSqs 		}
25713dec9fcdSqs 	}
25723dec9fcdSqs 
25733dec9fcdSqs 	mrf.mrf_type = MAC_RX_FIFO;
25743dec9fcdSqs 	mrf.mrf_blank = hxge_rx_hw_blank;
2575fe930412Sqs 	mrf.mrf_arg = (void *)hxgep;
25763dec9fcdSqs 
2577fe930412Sqs 	mrf.mrf_normal_blank_time = RXDMA_RCR_TO_DEFAULT;
2578fe930412Sqs 	mrf.mrf_normal_pkt_count = RXDMA_RCR_PTHRES_DEFAULT;
25793dec9fcdSqs 
25803dec9fcdSqs 	rcr_rings = hxgep->rx_rcr_rings;
25813dec9fcdSqs 	rcr_p = rcr_rings->rcr_rings;
25823dec9fcdSqs 	ndmas = rcr_rings->ndmas;
25833dec9fcdSqs 
25843dec9fcdSqs 	/*
25853dec9fcdSqs 	 * Export our receive resources to the MAC layer.
25863dec9fcdSqs 	 */
25873dec9fcdSqs 	for (i = 0; i < ndmas; i++) {
25883dec9fcdSqs 		rcrp = (void *)(p_rx_rcr_ring_t)rcr_p[i];
25893dec9fcdSqs 		rcrp->rcr_mac_handle =
25903dec9fcdSqs 		    mac_resource_add(hxgep->mach, (mac_resource_t *)&mrf);
25913dec9fcdSqs 
25923dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, RX_CTL,
25933dec9fcdSqs 		    "==> hxge_m_resources: vdma %d dma %d "
25943dec9fcdSqs 		    "rcrptr 0x%016llx mac_handle 0x%016llx",
25953dec9fcdSqs 		    i, rcrp->rdc, rcr_p[i], rcrp->rcr_mac_handle));
25963dec9fcdSqs 	}
25973dec9fcdSqs 
25983dec9fcdSqs 	MUTEX_EXIT(hxgep->genlock);
25993dec9fcdSqs 
26003dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_m_resources"));
26013dec9fcdSqs }
26023dec9fcdSqs 
26033dec9fcdSqs /*
26043dec9fcdSqs  * Set an alternate MAC address
26053dec9fcdSqs  */
26063dec9fcdSqs static int
26073dec9fcdSqs hxge_altmac_set(p_hxge_t hxgep, uint8_t *maddr, mac_addr_slot_t slot)
26083dec9fcdSqs {
26093dec9fcdSqs 	uint64_t	address;
26103dec9fcdSqs 	uint64_t	tmp;
26113dec9fcdSqs 	hpi_status_t	status;
26123dec9fcdSqs 	uint8_t		addrn;
26133dec9fcdSqs 	int		i;
26143dec9fcdSqs 
26153dec9fcdSqs 	/*
26163dec9fcdSqs 	 * Convert a byte array to a 48 bit value.
26173dec9fcdSqs 	 * Need to check endianess if in doubt
26183dec9fcdSqs 	 */
26193dec9fcdSqs 	address = 0;
26203dec9fcdSqs 	for (i = 0; i < ETHERADDRL; i++) {
26213dec9fcdSqs 		tmp = maddr[i];
26223dec9fcdSqs 		address <<= 8;
26233dec9fcdSqs 		address |= tmp;
26243dec9fcdSqs 	}
26253dec9fcdSqs 
26263dec9fcdSqs 	addrn = (uint8_t)slot;
26273dec9fcdSqs 	status = hpi_pfc_set_mac_address(hxgep->hpi_handle, addrn, address);
26283dec9fcdSqs 	if (status != HPI_SUCCESS)
26293dec9fcdSqs 		return (EIO);
26303dec9fcdSqs 
26313dec9fcdSqs 	return (0);
26323dec9fcdSqs }
26333dec9fcdSqs 
26343dec9fcdSqs static void
26353dec9fcdSqs hxge_mmac_kstat_update(p_hxge_t hxgep, mac_addr_slot_t slot)
26363dec9fcdSqs {
26373dec9fcdSqs 	p_hxge_mmac_stats_t	mmac_stats;
26383dec9fcdSqs 	int			i;
26393dec9fcdSqs 	hxge_mmac_t		*mmac_info;
26403dec9fcdSqs 
26413dec9fcdSqs 	mmac_info = &hxgep->hxge_mmac_info;
26423dec9fcdSqs 	mmac_stats = &hxgep->statsp->mmac_stats;
26433dec9fcdSqs 	mmac_stats->mmac_max_cnt = mmac_info->num_mmac;
26443dec9fcdSqs 	mmac_stats->mmac_avail_cnt = mmac_info->naddrfree;
26453dec9fcdSqs 
26463dec9fcdSqs 	for (i = 0; i < ETHERADDRL; i++) {
26473dec9fcdSqs 		mmac_stats->mmac_avail_pool[slot].ether_addr_octet[i] =
26483dec9fcdSqs 		    mmac_info->mac_pool[slot].addr[(ETHERADDRL - 1) - i];
26493dec9fcdSqs 	}
26503dec9fcdSqs }
26513dec9fcdSqs 
26523dec9fcdSqs /*
26533dec9fcdSqs  * Find an unused address slot, set the address value to the one specified,
26543dec9fcdSqs  * enable the port to start filtering on the new MAC address.
26553dec9fcdSqs  * Returns: 0 on success.
26563dec9fcdSqs  */
26573dec9fcdSqs int
26583dec9fcdSqs hxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr)
26593dec9fcdSqs {
26603dec9fcdSqs 	p_hxge_t	hxgep = arg;
26613dec9fcdSqs 	mac_addr_slot_t	slot;
26623dec9fcdSqs 	hxge_mmac_t	*mmac_info;
26633dec9fcdSqs 	int		err;
26643dec9fcdSqs 	hxge_status_t	status;
26653dec9fcdSqs 
26663dec9fcdSqs 	mutex_enter(hxgep->genlock);
26673dec9fcdSqs 
26683dec9fcdSqs 	/*
26693dec9fcdSqs 	 * Make sure that hxge is initialized, if _start() has
26703dec9fcdSqs 	 * not been called.
26713dec9fcdSqs 	 */
26723dec9fcdSqs 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
26733dec9fcdSqs 		status = hxge_init(hxgep);
26743dec9fcdSqs 		if (status != HXGE_OK) {
26753dec9fcdSqs 			mutex_exit(hxgep->genlock);
26763dec9fcdSqs 			return (ENXIO);
26773dec9fcdSqs 		}
26783dec9fcdSqs 	}
26793dec9fcdSqs 
26803dec9fcdSqs 	mmac_info = &hxgep->hxge_mmac_info;
26813dec9fcdSqs 	if (mmac_info->naddrfree == 0) {
26823dec9fcdSqs 		mutex_exit(hxgep->genlock);
26833dec9fcdSqs 		return (ENOSPC);
26843dec9fcdSqs 	}
26853dec9fcdSqs 
26863dec9fcdSqs 	if (!mac_unicst_verify(hxgep->mach, maddr->mma_addr,
26873dec9fcdSqs 	    maddr->mma_addrlen)) {
26883dec9fcdSqs 		mutex_exit(hxgep->genlock);
26893dec9fcdSqs 		return (EINVAL);
26903dec9fcdSqs 	}
26913dec9fcdSqs 
26923dec9fcdSqs 	/*
26933dec9fcdSqs 	 * Search for the first available slot. Because naddrfree
26943dec9fcdSqs 	 * is not zero, we are guaranteed to find one.
26953dec9fcdSqs 	 * Slot 0 is for unique (primary) MAC.  The first alternate
26963dec9fcdSqs 	 * MAC slot is slot 1.
26973dec9fcdSqs 	 */
26983dec9fcdSqs 	for (slot = 1; slot < mmac_info->num_mmac; slot++) {
26993dec9fcdSqs 		if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
27003dec9fcdSqs 			break;
27013dec9fcdSqs 	}
27023dec9fcdSqs 
27033dec9fcdSqs 	ASSERT(slot < mmac_info->num_mmac);
27043dec9fcdSqs 	if ((err = hxge_altmac_set(hxgep, maddr->mma_addr, slot)) != 0) {
27053dec9fcdSqs 		mutex_exit(hxgep->genlock);
27063dec9fcdSqs 		return (err);
27073dec9fcdSqs 	}
27083dec9fcdSqs 	bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, ETHERADDRL);
27093dec9fcdSqs 	mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED;
27103dec9fcdSqs 	mmac_info->naddrfree--;
27113dec9fcdSqs 	hxge_mmac_kstat_update(hxgep, slot);
27123dec9fcdSqs 
27133dec9fcdSqs 	maddr->mma_slot = slot;
27143dec9fcdSqs 
27153dec9fcdSqs 	mutex_exit(hxgep->genlock);
27163dec9fcdSqs 	return (0);
27173dec9fcdSqs }
27183dec9fcdSqs 
27193dec9fcdSqs /*
27203dec9fcdSqs  * Remove the specified mac address and update
27213dec9fcdSqs  * the h/w not to filter the mac address anymore.
27223dec9fcdSqs  * Returns: 0, on success.
27233dec9fcdSqs  */
27243dec9fcdSqs int
27253dec9fcdSqs hxge_m_mmac_remove(void *arg, mac_addr_slot_t slot)
27263dec9fcdSqs {
27273dec9fcdSqs 	p_hxge_t	hxgep = arg;
27283dec9fcdSqs 	hxge_mmac_t	*mmac_info;
27293dec9fcdSqs 	int		err = 0;
27303dec9fcdSqs 	hxge_status_t	status;
27313dec9fcdSqs 
27323dec9fcdSqs 	mutex_enter(hxgep->genlock);
27333dec9fcdSqs 
27343dec9fcdSqs 	/*
27353dec9fcdSqs 	 * Make sure that hxge is initialized, if _start() has
27363dec9fcdSqs 	 * not been called.
27373dec9fcdSqs 	 */
27383dec9fcdSqs 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
27393dec9fcdSqs 		status = hxge_init(hxgep);
27403dec9fcdSqs 		if (status != HXGE_OK) {
27413dec9fcdSqs 			mutex_exit(hxgep->genlock);
27423dec9fcdSqs 			return (ENXIO);
27433dec9fcdSqs 		}
27443dec9fcdSqs 	}
27453dec9fcdSqs 
27463dec9fcdSqs 	mmac_info = &hxgep->hxge_mmac_info;
27473dec9fcdSqs 	if (slot <= 0 || slot >= mmac_info->num_mmac) {
27483dec9fcdSqs 		mutex_exit(hxgep->genlock);
27493dec9fcdSqs 		return (EINVAL);
27503dec9fcdSqs 	}
27513dec9fcdSqs 
27523dec9fcdSqs 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
27533dec9fcdSqs 		if (hpi_pfc_mac_addr_disable(hxgep->hpi_handle, slot) ==
27543dec9fcdSqs 		    HPI_SUCCESS) {
27553dec9fcdSqs 			mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED;
27563dec9fcdSqs 			mmac_info->naddrfree++;
27573dec9fcdSqs 			/*
27583dec9fcdSqs 			 * Clear mac_pool[slot].addr so that kstat shows 0
27593dec9fcdSqs 			 * alternate MAC address if the slot is not used.
27603dec9fcdSqs 			 */
27613dec9fcdSqs 			bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL);
27623dec9fcdSqs 			hxge_mmac_kstat_update(hxgep, slot);
27633dec9fcdSqs 		} else {
27643dec9fcdSqs 			err = EIO;
27653dec9fcdSqs 		}
27663dec9fcdSqs 	} else {
27673dec9fcdSqs 		err = EINVAL;
27683dec9fcdSqs 	}
27693dec9fcdSqs 
27703dec9fcdSqs 	mutex_exit(hxgep->genlock);
27713dec9fcdSqs 	return (err);
27723dec9fcdSqs }
27733dec9fcdSqs 
27743dec9fcdSqs /*
27753dec9fcdSqs  * Modify a mac address added by hxge_mmac_add().
27763dec9fcdSqs  * Returns: 0, on success.
27773dec9fcdSqs  */
27783dec9fcdSqs int
27793dec9fcdSqs hxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr)
27803dec9fcdSqs {
27813dec9fcdSqs 	p_hxge_t	hxgep = arg;
27823dec9fcdSqs 	mac_addr_slot_t	slot;
27833dec9fcdSqs 	hxge_mmac_t	*mmac_info;
27843dec9fcdSqs 	int		err = 0;
27853dec9fcdSqs 	hxge_status_t	status;
27863dec9fcdSqs 
27873dec9fcdSqs 	if (!mac_unicst_verify(hxgep->mach, maddr->mma_addr,
27883dec9fcdSqs 	    maddr->mma_addrlen))
27893dec9fcdSqs 		return (EINVAL);
27903dec9fcdSqs 
27913dec9fcdSqs 	slot = maddr->mma_slot;
27923dec9fcdSqs 
27933dec9fcdSqs 	mutex_enter(hxgep->genlock);
27943dec9fcdSqs 
27953dec9fcdSqs 	/*
27963dec9fcdSqs 	 * Make sure that hxge is initialized, if _start() has
27973dec9fcdSqs 	 * not been called.
27983dec9fcdSqs 	 */
27993dec9fcdSqs 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
28003dec9fcdSqs 		status = hxge_init(hxgep);
28013dec9fcdSqs 		if (status != HXGE_OK) {
28023dec9fcdSqs 			mutex_exit(hxgep->genlock);
28033dec9fcdSqs 			return (ENXIO);
28043dec9fcdSqs 		}
28053dec9fcdSqs 	}
28063dec9fcdSqs 
28073dec9fcdSqs 	mmac_info = &hxgep->hxge_mmac_info;
28083dec9fcdSqs 	if (slot <= 0 || slot >= mmac_info->num_mmac) {
28093dec9fcdSqs 		mutex_exit(hxgep->genlock);
28103dec9fcdSqs 		return (EINVAL);
28113dec9fcdSqs 	}
28123dec9fcdSqs 
28133dec9fcdSqs 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
28143dec9fcdSqs 		if ((err = hxge_altmac_set(hxgep, maddr->mma_addr,
28153dec9fcdSqs 		    slot)) == 0) {
28163dec9fcdSqs 			bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr,
28173dec9fcdSqs 			    ETHERADDRL);
28183dec9fcdSqs 			hxge_mmac_kstat_update(hxgep, slot);
28193dec9fcdSqs 		}
28203dec9fcdSqs 	} else {
28213dec9fcdSqs 		err = EINVAL;
28223dec9fcdSqs 	}
28233dec9fcdSqs 
28243dec9fcdSqs 	mutex_exit(hxgep->genlock);
28253dec9fcdSqs 	return (err);
28263dec9fcdSqs }
28273dec9fcdSqs 
28283dec9fcdSqs /*
28293dec9fcdSqs  * static int
28303dec9fcdSqs  * hxge_m_mmac_get() - Get the MAC address and other information
28313dec9fcdSqs  *	related to the slot.  mma_flags should be set to 0 in the call.
28323dec9fcdSqs  *	Note: although kstat shows MAC address as zero when a slot is
28333dec9fcdSqs  *	not used, Crossbow expects hxge_m_mmac_get to copy factory MAC
28343dec9fcdSqs  *	to the caller as long as the slot is not using a user MAC address.
28353dec9fcdSqs  *	The following table shows the rules,
28363dec9fcdSqs  *
28373dec9fcdSqs  *     					USED    VENDOR    mma_addr
28383dec9fcdSqs  *	------------------------------------------------------------
28393dec9fcdSqs  *	(1) Slot uses a user MAC:	yes      no     user MAC
28403dec9fcdSqs  *	(2) Slot uses a factory MAC:    yes      yes    factory MAC
28413dec9fcdSqs  *	(3) Slot is not used but is
28423dec9fcdSqs  *	     factory MAC capable:	no       yes    factory MAC
28433dec9fcdSqs  *	(4) Slot is not used and is
28443dec9fcdSqs  *	     not factory MAC capable:   no       no	0
28453dec9fcdSqs  *	------------------------------------------------------------
28463dec9fcdSqs  */
28473dec9fcdSqs int
28483dec9fcdSqs hxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr)
28493dec9fcdSqs {
28503dec9fcdSqs 	hxge_t		*hxgep = arg;
28513dec9fcdSqs 	mac_addr_slot_t	slot;
28523dec9fcdSqs 	hxge_mmac_t	*mmac_info;
28533dec9fcdSqs 	hxge_status_t	status;
28543dec9fcdSqs 
28553dec9fcdSqs 	slot = maddr->mma_slot;
28563dec9fcdSqs 
28573dec9fcdSqs 	mutex_enter(hxgep->genlock);
28583dec9fcdSqs 
28593dec9fcdSqs 	/*
28603dec9fcdSqs 	 * Make sure that hxge is initialized, if _start() has
28613dec9fcdSqs 	 * not been called.
28623dec9fcdSqs 	 */
28633dec9fcdSqs 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
28643dec9fcdSqs 		status = hxge_init(hxgep);
28653dec9fcdSqs 		if (status != HXGE_OK) {
28663dec9fcdSqs 			mutex_exit(hxgep->genlock);
28673dec9fcdSqs 			return (ENXIO);
28683dec9fcdSqs 		}
28693dec9fcdSqs 	}
28703dec9fcdSqs 
28713dec9fcdSqs 	mmac_info = &hxgep->hxge_mmac_info;
28723dec9fcdSqs 	if (slot <= 0 || slot >= mmac_info->num_mmac) {
28733dec9fcdSqs 		mutex_exit(hxgep->genlock);
28743dec9fcdSqs 		return (EINVAL);
28753dec9fcdSqs 	}
28763dec9fcdSqs 
28773dec9fcdSqs 	maddr->mma_flags = 0;
28783dec9fcdSqs 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
28793dec9fcdSqs 		maddr->mma_flags |= MMAC_SLOT_USED;
28803dec9fcdSqs 		bcopy(mmac_info->mac_pool[slot].addr,
28813dec9fcdSqs 		    maddr->mma_addr, ETHERADDRL);
28823dec9fcdSqs 		maddr->mma_addrlen = ETHERADDRL;
28833dec9fcdSqs 	}
28843dec9fcdSqs 
28853dec9fcdSqs 	mutex_exit(hxgep->genlock);
28863dec9fcdSqs 	return (0);
28873dec9fcdSqs }
28883dec9fcdSqs 
28893dec9fcdSqs /*ARGSUSED*/
28903dec9fcdSqs boolean_t
28913dec9fcdSqs hxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
28923dec9fcdSqs {
28933dec9fcdSqs 	p_hxge_t		hxgep = (p_hxge_t)arg;
28943dec9fcdSqs 	uint32_t		*txflags = cap_data;
28953dec9fcdSqs 	multiaddress_capab_t	*mmacp = cap_data;
28963dec9fcdSqs 
28973dec9fcdSqs 	switch (cap) {
28983dec9fcdSqs 	case MAC_CAPAB_HCKSUM:
28993dec9fcdSqs 		*txflags = HCKSUM_INET_PARTIAL;
29003dec9fcdSqs 		break;
29013dec9fcdSqs 
29023dec9fcdSqs 	case MAC_CAPAB_POLL:
29033dec9fcdSqs 		/*
29043dec9fcdSqs 		 * There's nothing for us to fill in, simply returning B_TRUE
29053dec9fcdSqs 		 * stating that we support polling is sufficient.
29063dec9fcdSqs 		 */
29073dec9fcdSqs 		break;
29083dec9fcdSqs 
29093dec9fcdSqs 	case MAC_CAPAB_MULTIADDRESS:
29103dec9fcdSqs 		/*
29113dec9fcdSqs 		 * The number of MAC addresses made available by
29123dec9fcdSqs 		 * this capability is one less than the total as
29133dec9fcdSqs 		 * the primary address in slot 0 is counted in
29143dec9fcdSqs 		 * the total.
29153dec9fcdSqs 		 */
29163dec9fcdSqs 		mmacp->maddr_naddr = PFC_N_MAC_ADDRESSES - 1;
29173dec9fcdSqs 		mmacp->maddr_naddrfree = hxgep->hxge_mmac_info.naddrfree;
29183dec9fcdSqs 		mmacp->maddr_flag = 0;	/* No multiple factory macs */
29193dec9fcdSqs 		mmacp->maddr_handle = hxgep;
29203dec9fcdSqs 		mmacp->maddr_add = hxge_m_mmac_add;
29213dec9fcdSqs 		mmacp->maddr_remove = hxge_m_mmac_remove;
29223dec9fcdSqs 		mmacp->maddr_modify = hxge_m_mmac_modify;
29233dec9fcdSqs 		mmacp->maddr_get = hxge_m_mmac_get;
29243dec9fcdSqs 		mmacp->maddr_reserve = NULL;	/* No multiple factory macs */
29253dec9fcdSqs 		break;
29263dec9fcdSqs 	default:
29273dec9fcdSqs 		return (B_FALSE);
29283dec9fcdSqs 	}
29293dec9fcdSqs 	return (B_TRUE);
29303dec9fcdSqs }
29313dec9fcdSqs 
2932*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static boolean_t
2933*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_param_locked(mac_prop_id_t pr_num)
2934*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {
2935*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	/*
2936*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	 * All adv_* parameters are locked (read-only) while
2937*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	 * the device is in any sort of loopback mode ...
2938*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	 */
2939*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	switch (pr_num) {
2940*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_1000FDX_CAP:
2941*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_1000FDX_CAP:
2942*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_1000HDX_CAP:
2943*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_1000HDX_CAP:
2944*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_100FDX_CAP:
2945*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_100FDX_CAP:
2946*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_100HDX_CAP:
2947*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_100HDX_CAP:
2948*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_10FDX_CAP:
2949*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_10FDX_CAP:
2950*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_10HDX_CAP:
2951*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_10HDX_CAP:
2952*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_AUTONEG:
2953*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_FLOWCTRL:
2954*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			return (B_TRUE);
2955*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
2956*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	return (B_FALSE);
2957*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States }
2958*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
2959*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /*
2960*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States  * callback functions for set/get of properties
2961*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States  */
2962*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int
2963*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
2964*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States     uint_t pr_valsize, const void *pr_val)
2965*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {
2966*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxge_t		*hxgep = barg;
2967*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	p_hxge_stats_t	statsp;
2968*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	int		err = 0;
2969*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	uint32_t	new_mtu, old_framesize, new_framesize;
2970*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
2971*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "==> hxge_m_setprop"));
2972*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
2973*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	statsp = hxgep->statsp;
2974*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	mutex_enter(hxgep->genlock);
2975*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if (statsp->port_stats.lb_mode != hxge_lb_normal &&
2976*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	    hxge_param_locked(pr_num)) {
2977*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		/*
2978*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		 * All adv_* parameters are locked (read-only)
2979*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		 * while the device is in any sort of loopback mode.
2980*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		 */
2981*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
2982*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    "==> hxge_m_setprop: loopback mode: read only"));
2983*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		mutex_exit(hxgep->genlock);
2984*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		return (EBUSY);
2985*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
2986*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
2987*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	switch (pr_num) {
2988*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		/*
2989*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		 * These properties are either not exist or read only
2990*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		 */
2991*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_1000FDX_CAP:
2992*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_100FDX_CAP:
2993*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_10FDX_CAP:
2994*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_1000HDX_CAP:
2995*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_100HDX_CAP:
2996*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_10HDX_CAP:
2997*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_1000FDX_CAP:
2998*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_1000HDX_CAP:
2999*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_100FDX_CAP:
3000*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_100HDX_CAP:
3001*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_10FDX_CAP:
3002*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_10HDX_CAP:
3003*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_STATUS:
3004*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_SPEED:
3005*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_DUPLEX:
3006*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_AUTONEG:
3007*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		/*
3008*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		 * Flow control is handled in the shared domain and
3009*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		 * it is readonly here.
3010*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		 */
3011*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_FLOWCTRL:
3012*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = EINVAL;
3013*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3014*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    "==> hxge_m_setprop:  read only property %d",
3015*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    pr_num));
3016*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3017*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3018*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_MTU:
3019*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			if (hxgep->hxge_mac_state == HXGE_MAC_STARTED) {
3020*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				err = EBUSY;
3021*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				break;
3022*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			}
3023*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3024*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			bcopy(pr_val, &new_mtu, sizeof (new_mtu));
3025*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3026*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    "==> hxge_m_setprop: set MTU: %d", new_mtu));
3027*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3028*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			new_framesize = new_mtu + MTU_TO_FRAME_SIZE;
3029*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			if (new_framesize == hxgep->vmac.maxframesize) {
3030*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				err = 0;
3031*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				break;
3032*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			}
3033*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3034*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			if (new_framesize < MIN_FRAME_SIZE ||
3035*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    new_framesize > MAX_FRAME_SIZE) {
3036*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				err = EINVAL;
3037*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				break;
3038*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			}
3039*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3040*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			old_framesize = hxgep->vmac.maxframesize;
3041*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			hxgep->vmac.maxframesize = (uint16_t)new_framesize;
3042*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3043*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			if (hxge_vmac_set_framesize(hxgep)) {
3044*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				hxgep->vmac.maxframesize =
3045*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				    (uint16_t)old_framesize;
3046*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				err = EINVAL;
3047*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				break;
3048*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			}
3049*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3050*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = mac_maxsdu_update(hxgep->mach, new_mtu);
3051*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			if (err) {
3052*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				hxgep->vmac.maxframesize =
3053*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				    (uint16_t)old_framesize;
3054*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				(void) hxge_vmac_set_framesize(hxgep);
3055*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			}
3056*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3057*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3058*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    "==> hxge_m_setprop: set MTU: %d maxframe %d",
3059*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    new_mtu, hxgep->vmac.maxframesize));
3060*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3061*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3062*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_PRIVATE:
3063*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3064*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    "==> hxge_m_setprop: private property"));
3065*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = hxge_set_priv_prop(hxgep, pr_name, pr_valsize,
3066*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    pr_val);
3067*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3068*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3069*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		default:
3070*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = ENOTSUP;
3071*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3072*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
3073*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3074*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	mutex_exit(hxgep->genlock);
3075*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3076*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3077*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	    "<== hxge_m_setprop (return %d)", err));
3078*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3079*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	return (err);
3080*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States }
3081*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3082*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* ARGSUSED */
3083*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int
3084*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_get_def_val(hxge_t *hxgep, mac_prop_id_t pr_num, uint_t pr_valsize,
3085*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States     void *pr_val)
3086*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {
3087*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	int		err = 0;
3088*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	link_flowctrl_t	fl;
3089*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3090*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	switch (pr_num) {
3091*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	case MAC_PROP_DUPLEX:
3092*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		*(uint8_t *)pr_val = 2;
3093*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		break;
3094*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	case MAC_PROP_AUTONEG:
3095*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		*(uint8_t *)pr_val = 0;
3096*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		break;
3097*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	case MAC_PROP_FLOWCTRL:
3098*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		if (pr_valsize < sizeof (link_flowctrl_t))
3099*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			return (EINVAL);
3100*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		fl = LINK_FLOWCTRL_TX;
3101*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		bcopy(&fl, pr_val, sizeof (fl));
3102*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		break;
3103*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	default:
3104*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = ENOTSUP;
3105*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		break;
3106*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
3107*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	return (err);
3108*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States }
3109*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3110*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int
3111*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
3112*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States     uint_t pr_flags, uint_t pr_valsize, void *pr_val)
3113*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {
3114*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxge_t 		*hxgep = barg;
3115*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	p_hxge_stats_t	statsp = hxgep->statsp;
3116*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	int		err = 0;
3117*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	link_flowctrl_t fl;
3118*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	uint64_t	tmp = 0;
3119*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	link_state_t	ls;
3120*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3121*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3122*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	    "==> hxge_m_getprop: pr_num %d", pr_num));
3123*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3124*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if (pr_valsize == 0)
3125*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		return (EINVAL);
3126*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3127*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if ((pr_flags & MAC_PROP_DEFAULT) && (pr_num != MAC_PROP_PRIVATE)) {
3128*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_get_def_val(hxgep, pr_num, pr_valsize, pr_val);
3129*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		return (err);
3130*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
3131*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3132*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	bzero(pr_val, pr_valsize);
3133*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	switch (pr_num) {
3134*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_DUPLEX:
3135*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			*(uint8_t *)pr_val = statsp->mac_stats.link_duplex;
3136*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3137*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    "==> hxge_m_getprop: duplex mode %d",
3138*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    *(uint8_t *)pr_val));
3139*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3140*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3141*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_SPEED:
3142*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			if (pr_valsize < sizeof (uint64_t))
3143*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				return (EINVAL);
3144*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			tmp = statsp->mac_stats.link_speed * 1000000ull;
3145*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			bcopy(&tmp, pr_val, sizeof (tmp));
3146*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3147*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3148*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_STATUS:
3149*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			if (pr_valsize < sizeof (link_state_t))
3150*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				return (EINVAL);
3151*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			if (!statsp->mac_stats.link_up)
3152*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				ls = LINK_STATE_DOWN;
3153*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			else
3154*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				ls = LINK_STATE_UP;
3155*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			bcopy(&ls, pr_val, sizeof (ls));
3156*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3157*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3158*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_FLOWCTRL:
3159*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			/*
3160*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			 * Flow control is supported by the shared domain and
3161*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			 * it is currently transmit only
3162*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			 */
3163*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			if (pr_valsize < sizeof (link_flowctrl_t))
3164*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 				return (EINVAL);
3165*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			fl = LINK_FLOWCTRL_TX;
3166*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			bcopy(&fl, pr_val, sizeof (fl));
3167*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3168*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_AUTONEG:
3169*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			/* 10G link only and it is not negotiable */
3170*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			*(uint8_t *)pr_val = 0;
3171*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3172*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_1000FDX_CAP:
3173*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_100FDX_CAP:
3174*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_10FDX_CAP:
3175*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_1000HDX_CAP:
3176*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_100HDX_CAP:
3177*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_ADV_10HDX_CAP:
3178*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_1000FDX_CAP:
3179*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_100FDX_CAP:
3180*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_10FDX_CAP:
3181*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_1000HDX_CAP:
3182*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_100HDX_CAP:
3183*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_EN_10HDX_CAP:
3184*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = ENOTSUP;
3185*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3186*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3187*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		case MAC_PROP_PRIVATE:
3188*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = hxge_get_priv_prop(hxgep, pr_name, pr_flags,
3189*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    pr_valsize, pr_val);
3190*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3191*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		default:
3192*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = EINVAL;
3193*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			break;
3194*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
3195*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3196*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "<== hxge_m_getprop"));
3197*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3198*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	return (err);
3199*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States }
3200*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3201*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* ARGSUSED */
3202*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int
3203*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize,
3204*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States     const void *pr_val)
3205*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {
3206*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	p_hxge_param_t	param_arr = hxgep->param_arr;
3207*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	int		err = 0;
3208*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3209*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3210*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	    "==> hxge_set_priv_prop: name %s (value %s)", pr_name, pr_val));
3211*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3212*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if (pr_val == NULL) {
3213*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		return (EINVAL);
3214*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
3215*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3216*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	/* Blanking */
3217*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
3218*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_param_rx_intr_time(hxgep, NULL, NULL,
3219*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    (char *)pr_val, (caddr_t)&param_arr[param_rxdma_intr_time]);
3220*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
3221*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_param_rx_intr_pkts(hxgep, NULL, NULL,
3222*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    (char *)pr_val, (caddr_t)&param_arr[param_rxdma_intr_pkts]);
3223*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3224*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	/* Classification */
3225*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
3226*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3227*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    (caddr_t)&param_arr[param_class_opt_ipv4_tcp]);
3228*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
3229*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3230*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    (caddr_t)&param_arr[param_class_opt_ipv4_udp]);
3231*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
3232*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3233*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    (caddr_t)&param_arr[param_class_opt_ipv4_ah]);
3234*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
3235*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3236*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    (caddr_t)&param_arr[param_class_opt_ipv4_sctp]);
3237*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
3238*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3239*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    (caddr_t)&param_arr[param_class_opt_ipv6_tcp]);
3240*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
3241*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3242*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    (caddr_t)&param_arr[param_class_opt_ipv6_udp]);
3243*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
3244*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3245*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    (caddr_t)&param_arr[param_class_opt_ipv6_ah]);
3246*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
3247*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3248*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    (caddr_t)&param_arr[param_class_opt_ipv6_sctp]);
3249*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else {
3250*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		err = EINVAL;
3251*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
3252*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3253*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3254*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	    "<== hxge_set_priv_prop: err %d", err));
3255*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3256*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	return (err);
3257*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States }
3258*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3259*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static int
3260*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_flags,
3261*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States     uint_t pr_valsize, void *pr_val)
3262*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {
3263*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	p_hxge_param_t	param_arr = hxgep->param_arr;
3264*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	char		valstr[MAXNAMELEN];
3265*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	int		err = 0;
3266*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	uint_t		strsize;
3267*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	int		value = 0;
3268*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3269*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3270*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	    "==> hxge_get_priv_prop: property %s", pr_name));
3271*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3272*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if (pr_flags & MAC_PROP_DEFAULT) {
3273*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		/* Receive Interrupt Blanking Parameters */
3274*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
3275*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = RXDMA_RCR_TO_DEFAULT;
3276*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
3277*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = RXDMA_RCR_PTHRES_DEFAULT;
3278*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3279*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		/* Classification and Load Distribution Configuration */
3280*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 ||
3281*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    strcmp(pr_name, "_class_opt_ipv4_udp") == 0 ||
3282*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    strcmp(pr_name, "_class_opt_ipv4_ah") == 0 ||
3283*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 ||
3284*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 ||
3285*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    strcmp(pr_name, "_class_opt_ipv6_udp") == 0 ||
3286*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    strcmp(pr_name, "_class_opt_ipv6_ah") == 0 ||
3287*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		    strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
3288*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = HXGE_CLASS_TCAM_LOOKUP;
3289*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else {
3290*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = EINVAL;
3291*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		}
3292*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	} else {
3293*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		/* Receive Interrupt Blanking Parameters */
3294*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
3295*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = hxgep->intr_timeout;
3296*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
3297*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = hxgep->intr_threshold;
3298*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3299*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		/* Classification and Load Distribution Configuration */
3300*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
3301*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3302*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    (caddr_t)&param_arr[param_class_opt_ipv4_tcp]);
3303*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3304*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = (int)param_arr[param_class_opt_ipv4_tcp].value;
3305*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
3306*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3307*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    (caddr_t)&param_arr[param_class_opt_ipv4_udp]);
3308*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3309*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = (int)param_arr[param_class_opt_ipv4_udp].value;
3310*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
3311*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3312*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    (caddr_t)&param_arr[param_class_opt_ipv4_ah]);
3313*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3314*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = (int)param_arr[param_class_opt_ipv4_ah].value;
3315*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
3316*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3317*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    (caddr_t)&param_arr[param_class_opt_ipv4_sctp]);
3318*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3319*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = (int)param_arr[param_class_opt_ipv4_sctp].value;
3320*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
3321*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3322*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    (caddr_t)&param_arr[param_class_opt_ipv6_tcp]);
3323*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3324*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = (int)param_arr[param_class_opt_ipv6_tcp].value;
3325*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
3326*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3327*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    (caddr_t)&param_arr[param_class_opt_ipv6_udp]);
3328*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3329*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = (int)param_arr[param_class_opt_ipv6_udp].value;
3330*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
3331*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3332*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    (caddr_t)&param_arr[param_class_opt_ipv6_ah]);
3333*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3334*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = (int)param_arr[param_class_opt_ipv6_ah].value;
3335*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
3336*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3337*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			    (caddr_t)&param_arr[param_class_opt_ipv6_sctp]);
3338*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3339*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			value = (int)param_arr[param_class_opt_ipv6_sctp].value;
3340*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else {
3341*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = EINVAL;
3342*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		}
3343*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
3344*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3345*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if (err == 0) {
3346*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		(void) snprintf(valstr, sizeof (valstr), "0x%x", value);
3347*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3348*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		strsize = (uint_t)strlen(valstr);
3349*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		if (pr_valsize < strsize) {
3350*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			err = ENOBUFS;
3351*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else {
3352*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			(void) strlcpy(pr_val, valstr, pr_valsize);
3353*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		}
3354*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
3355*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3356*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3357*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	    "<== hxge_get_priv_prop: return %d", err));
3358*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
3359*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	return (err);
3360*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States }
33613dec9fcdSqs /*
33623dec9fcdSqs  * Module loading and removing entry points.
33633dec9fcdSqs  */
33643dec9fcdSqs DDI_DEFINE_STREAM_OPS(hxge_dev_ops, nulldev, nulldev, hxge_attach, hxge_detach,
33653dec9fcdSqs     nodev, NULL, D_MP, NULL);
33663dec9fcdSqs 
33673dec9fcdSqs extern struct mod_ops mod_driverops;
33683dec9fcdSqs 
33693dec9fcdSqs #define	HXGE_DESC_VER	"HXGE 10Gb Ethernet Driver"
33703dec9fcdSqs 
33713dec9fcdSqs /*
33723dec9fcdSqs  * Module linkage information for the kernel.
33733dec9fcdSqs  */
33743dec9fcdSqs static struct modldrv hxge_modldrv = {
33753dec9fcdSqs 	&mod_driverops,
33763dec9fcdSqs 	HXGE_DESC_VER,
33773dec9fcdSqs 	&hxge_dev_ops
33783dec9fcdSqs };
33793dec9fcdSqs 
33803dec9fcdSqs static struct modlinkage modlinkage = {
33813dec9fcdSqs 	MODREV_1, (void *) &hxge_modldrv, NULL
33823dec9fcdSqs };
33833dec9fcdSqs 
33843dec9fcdSqs int
33853dec9fcdSqs _init(void)
33863dec9fcdSqs {
33873dec9fcdSqs 	int status;
33883dec9fcdSqs 
33893dec9fcdSqs 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init"));
33903dec9fcdSqs 	mac_init_ops(&hxge_dev_ops, "hxge");
33913dec9fcdSqs 	status = ddi_soft_state_init(&hxge_list, sizeof (hxge_t), 0);
33923dec9fcdSqs 	if (status != 0) {
33933dec9fcdSqs 		HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL,
33943dec9fcdSqs 		    "failed to init device soft state"));
33953dec9fcdSqs 		mac_fini_ops(&hxge_dev_ops);
33963dec9fcdSqs 		goto _init_exit;
33973dec9fcdSqs 	}
33983dec9fcdSqs 
33993dec9fcdSqs 	status = mod_install(&modlinkage);
34003dec9fcdSqs 	if (status != 0) {
34013dec9fcdSqs 		ddi_soft_state_fini(&hxge_list);
34023dec9fcdSqs 		HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, "Mod install failed"));
34033dec9fcdSqs 		goto _init_exit;
34043dec9fcdSqs 	}
34053dec9fcdSqs 
34063dec9fcdSqs 	MUTEX_INIT(&hxge_common_lock, NULL, MUTEX_DRIVER, NULL);
34073dec9fcdSqs 
34083dec9fcdSqs _init_exit:
34093dec9fcdSqs 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status));
34103dec9fcdSqs 
34113dec9fcdSqs 	return (status);
34123dec9fcdSqs }
34133dec9fcdSqs 
34143dec9fcdSqs int
34153dec9fcdSqs _fini(void)
34163dec9fcdSqs {
34173dec9fcdSqs 	int status;
34183dec9fcdSqs 
34193dec9fcdSqs 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini"));
34203dec9fcdSqs 
34213dec9fcdSqs 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove"));
34223dec9fcdSqs 
34233dec9fcdSqs 	if (hxge_mblks_pending)
34243dec9fcdSqs 		return (EBUSY);
34253dec9fcdSqs 
34263dec9fcdSqs 	status = mod_remove(&modlinkage);
34273dec9fcdSqs 	if (status != DDI_SUCCESS) {
34283dec9fcdSqs 		HXGE_DEBUG_MSG((NULL, MOD_CTL,
34293dec9fcdSqs 		    "Module removal failed 0x%08x", status));
34303dec9fcdSqs 		goto _fini_exit;
34313dec9fcdSqs 	}
34323dec9fcdSqs 
34333dec9fcdSqs 	mac_fini_ops(&hxge_dev_ops);
34343dec9fcdSqs 
34353dec9fcdSqs 	ddi_soft_state_fini(&hxge_list);
34363dec9fcdSqs 
34373dec9fcdSqs 	MUTEX_DESTROY(&hxge_common_lock);
34383dec9fcdSqs 
34393dec9fcdSqs _fini_exit:
34403dec9fcdSqs 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status));
34413dec9fcdSqs 
34423dec9fcdSqs 	return (status);
34433dec9fcdSqs }
34443dec9fcdSqs 
34453dec9fcdSqs int
34463dec9fcdSqs _info(struct modinfo *modinfop)
34473dec9fcdSqs {
34483dec9fcdSqs 	int status;
34493dec9fcdSqs 
34503dec9fcdSqs 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info"));
34513dec9fcdSqs 	status = mod_info(&modlinkage, modinfop);
34523dec9fcdSqs 	HXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status));
34533dec9fcdSqs 
34543dec9fcdSqs 	return (status);
34553dec9fcdSqs }
34563dec9fcdSqs 
34573dec9fcdSqs /*ARGSUSED*/
34583dec9fcdSqs hxge_status_t
34593dec9fcdSqs hxge_add_intrs(p_hxge_t hxgep)
34603dec9fcdSqs {
34613dec9fcdSqs 	int		intr_types;
34623dec9fcdSqs 	int		type = 0;
34633dec9fcdSqs 	int		ddi_status = DDI_SUCCESS;
34643dec9fcdSqs 	hxge_status_t	status = HXGE_OK;
34653dec9fcdSqs 
34663dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs"));
34673dec9fcdSqs 
34683dec9fcdSqs 	hxgep->hxge_intr_type.intr_registered = B_FALSE;
34693dec9fcdSqs 	hxgep->hxge_intr_type.intr_enabled = B_FALSE;
34703dec9fcdSqs 	hxgep->hxge_intr_type.msi_intx_cnt = 0;
34713dec9fcdSqs 	hxgep->hxge_intr_type.intr_added = 0;
34723dec9fcdSqs 	hxgep->hxge_intr_type.niu_msi_enable = B_FALSE;
34733dec9fcdSqs 	hxgep->hxge_intr_type.intr_type = 0;
34743dec9fcdSqs 
34753dec9fcdSqs 	if (hxge_msi_enable) {
34763dec9fcdSqs 		hxgep->hxge_intr_type.niu_msi_enable = B_TRUE;
34773dec9fcdSqs 	}
34783dec9fcdSqs 
34793dec9fcdSqs 	/* Get the supported interrupt types */
34803dec9fcdSqs 	if ((ddi_status = ddi_intr_get_supported_types(hxgep->dip, &intr_types))
34813dec9fcdSqs 	    != DDI_SUCCESS) {
34823dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_intrs: "
34833dec9fcdSqs 		    "ddi_intr_get_supported_types failed: status 0x%08x",
34843dec9fcdSqs 		    ddi_status));
34853dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
34863dec9fcdSqs 	}
34873dec9fcdSqs 
34883dec9fcdSqs 	hxgep->hxge_intr_type.intr_types = intr_types;
34893dec9fcdSqs 
34903dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
34913dec9fcdSqs 	    "ddi_intr_get_supported_types: 0x%08x", intr_types));
34923dec9fcdSqs 
34933dec9fcdSqs 	/*
34943dec9fcdSqs 	 * Pick the interrupt type to use MSIX, MSI, INTX hxge_msi_enable:
34953dec9fcdSqs 	 *	(1): 1 - MSI
34963dec9fcdSqs 	 *	(2): 2 - MSI-X
34973dec9fcdSqs 	 *	others - FIXED
34983dec9fcdSqs 	 */
34993dec9fcdSqs 	switch (hxge_msi_enable) {
35003dec9fcdSqs 	default:
35013dec9fcdSqs 		type = DDI_INTR_TYPE_FIXED;
35023dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
35033dec9fcdSqs 		    "use fixed (intx emulation) type %08x", type));
35043dec9fcdSqs 		break;
35053dec9fcdSqs 
35063dec9fcdSqs 	case 2:
35073dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
35083dec9fcdSqs 		    "ddi_intr_get_supported_types: 0x%08x", intr_types));
35093dec9fcdSqs 		if (intr_types & DDI_INTR_TYPE_MSIX) {
35103dec9fcdSqs 			type = DDI_INTR_TYPE_MSIX;
35113dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
35123dec9fcdSqs 			    "==> hxge_add_intrs: "
35133dec9fcdSqs 			    "ddi_intr_get_supported_types: MSIX 0x%08x", type));
35143dec9fcdSqs 		} else if (intr_types & DDI_INTR_TYPE_MSI) {
35153dec9fcdSqs 			type = DDI_INTR_TYPE_MSI;
35163dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
35173dec9fcdSqs 			    "==> hxge_add_intrs: "
35183dec9fcdSqs 			    "ddi_intr_get_supported_types: MSI 0x%08x", type));
35193dec9fcdSqs 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
35203dec9fcdSqs 			type = DDI_INTR_TYPE_FIXED;
35213dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
35223dec9fcdSqs 			    "ddi_intr_get_supported_types: MSXED0x%08x", type));
35233dec9fcdSqs 		}
35243dec9fcdSqs 		break;
35253dec9fcdSqs 
35263dec9fcdSqs 	case 1:
35273dec9fcdSqs 		if (intr_types & DDI_INTR_TYPE_MSI) {
35283dec9fcdSqs 			type = DDI_INTR_TYPE_MSI;
35293dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
35303dec9fcdSqs 			    "==> hxge_add_intrs: "
35313dec9fcdSqs 			    "ddi_intr_get_supported_types: MSI 0x%08x", type));
35323dec9fcdSqs 		} else if (intr_types & DDI_INTR_TYPE_MSIX) {
35333dec9fcdSqs 			type = DDI_INTR_TYPE_MSIX;
35343dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
35353dec9fcdSqs 			    "==> hxge_add_intrs: "
35363dec9fcdSqs 			    "ddi_intr_get_supported_types: MSIX 0x%08x", type));
35373dec9fcdSqs 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
35383dec9fcdSqs 			type = DDI_INTR_TYPE_FIXED;
35393dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
35403dec9fcdSqs 			    "==> hxge_add_intrs: "
35413dec9fcdSqs 			    "ddi_intr_get_supported_types: MSXED0x%08x", type));
35423dec9fcdSqs 		}
35433dec9fcdSqs 	}
35443dec9fcdSqs 
35453dec9fcdSqs 	hxgep->hxge_intr_type.intr_type = type;
35463dec9fcdSqs 	if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI ||
35473dec9fcdSqs 	    type == DDI_INTR_TYPE_FIXED) &&
35483dec9fcdSqs 	    hxgep->hxge_intr_type.niu_msi_enable) {
35493dec9fcdSqs 		if ((status = hxge_add_intrs_adv(hxgep)) != DDI_SUCCESS) {
35503dec9fcdSqs 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
35513dec9fcdSqs 			    " hxge_add_intrs: "
35523dec9fcdSqs 			    " hxge_add_intrs_adv failed: status 0x%08x",
35533dec9fcdSqs 			    status));
35543dec9fcdSqs 			return (status);
35553dec9fcdSqs 		} else {
35563dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_intrs: "
35573dec9fcdSqs 			    "interrupts registered : type %d", type));
35583dec9fcdSqs 			hxgep->hxge_intr_type.intr_registered = B_TRUE;
35593dec9fcdSqs 
35603dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
35613dec9fcdSqs 			    "\nAdded advanced hxge add_intr_adv "
35623dec9fcdSqs 			    "intr type 0x%x\n", type));
35633dec9fcdSqs 
35643dec9fcdSqs 			return (status);
35653dec9fcdSqs 		}
35663dec9fcdSqs 	}
35673dec9fcdSqs 
35683dec9fcdSqs 	if (!hxgep->hxge_intr_type.intr_registered) {
35693dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
35703dec9fcdSqs 		    "==> hxge_add_intrs: failed to register interrupts"));
35713dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
35723dec9fcdSqs 	}
35733dec9fcdSqs 
35743dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs"));
35753dec9fcdSqs 
35763dec9fcdSqs 	return (status);
35773dec9fcdSqs }
35783dec9fcdSqs 
35793dec9fcdSqs /*ARGSUSED*/
35803dec9fcdSqs static hxge_status_t
35813dec9fcdSqs hxge_add_soft_intrs(p_hxge_t hxgep)
35823dec9fcdSqs {
35833dec9fcdSqs 	int		ddi_status = DDI_SUCCESS;
35843dec9fcdSqs 	hxge_status_t	status = HXGE_OK;
35853dec9fcdSqs 
35863dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_soft_intrs"));
35873dec9fcdSqs 
35883dec9fcdSqs 	hxgep->resched_id = NULL;
35893dec9fcdSqs 	hxgep->resched_running = B_FALSE;
35903dec9fcdSqs 	ddi_status = ddi_add_softintr(hxgep->dip, DDI_SOFTINT_LOW,
35913dec9fcdSqs 	    &hxgep->resched_id, NULL, NULL, hxge_reschedule, (caddr_t)hxgep);
35923dec9fcdSqs 	if (ddi_status != DDI_SUCCESS) {
35933dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_soft_intrs: "
35943dec9fcdSqs 		    "ddi_add_softintrs failed: status 0x%08x", ddi_status));
35953dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
35963dec9fcdSqs 	}
35973dec9fcdSqs 
35983dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_ddi_add_soft_intrs"));
35993dec9fcdSqs 
36003dec9fcdSqs 	return (status);
36013dec9fcdSqs }
36023dec9fcdSqs 
36033dec9fcdSqs /*ARGSUSED*/
36043dec9fcdSqs static hxge_status_t
36053dec9fcdSqs hxge_add_intrs_adv(p_hxge_t hxgep)
36063dec9fcdSqs {
36073dec9fcdSqs 	int		intr_type;
36083dec9fcdSqs 	p_hxge_intr_t	intrp;
36093dec9fcdSqs 	hxge_status_t	status;
36103dec9fcdSqs 
36113dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv"));
36123dec9fcdSqs 
36133dec9fcdSqs 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
36143dec9fcdSqs 	intr_type = intrp->intr_type;
36153dec9fcdSqs 
36163dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv: type 0x%x",
36173dec9fcdSqs 	    intr_type));
36183dec9fcdSqs 
36193dec9fcdSqs 	switch (intr_type) {
36203dec9fcdSqs 	case DDI_INTR_TYPE_MSI:		/* 0x2 */
36213dec9fcdSqs 	case DDI_INTR_TYPE_MSIX:	/* 0x4 */
36223dec9fcdSqs 		status = hxge_add_intrs_adv_type(hxgep, intr_type);
36233dec9fcdSqs 		break;
36243dec9fcdSqs 
36253dec9fcdSqs 	case DDI_INTR_TYPE_FIXED:	/* 0x1 */
36263dec9fcdSqs 		status = hxge_add_intrs_adv_type_fix(hxgep, intr_type);
36273dec9fcdSqs 		break;
36283dec9fcdSqs 
36293dec9fcdSqs 	default:
36303dec9fcdSqs 		status = HXGE_ERROR;
36313dec9fcdSqs 		break;
36323dec9fcdSqs 	}
36333dec9fcdSqs 
36343dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv"));
36353dec9fcdSqs 
36363dec9fcdSqs 	return (status);
36373dec9fcdSqs }
36383dec9fcdSqs 
36393dec9fcdSqs /*ARGSUSED*/
36403dec9fcdSqs static hxge_status_t
36413dec9fcdSqs hxge_add_intrs_adv_type(p_hxge_t hxgep, uint32_t int_type)
36423dec9fcdSqs {
36433dec9fcdSqs 	dev_info_t	*dip = hxgep->dip;
36443dec9fcdSqs 	p_hxge_ldg_t	ldgp;
36453dec9fcdSqs 	p_hxge_intr_t	intrp;
36463dec9fcdSqs 	uint_t		*inthandler;
36473dec9fcdSqs 	void		*arg1, *arg2;
36483dec9fcdSqs 	int		behavior;
36493dec9fcdSqs 	int		nintrs, navail;
36503dec9fcdSqs 	int		nactual, nrequired;
36513dec9fcdSqs 	int		inum = 0;
36523dec9fcdSqs 	int		loop = 0;
36533dec9fcdSqs 	int		x, y;
36543dec9fcdSqs 	int		ddi_status = DDI_SUCCESS;
36553dec9fcdSqs 	hxge_status_t	status = HXGE_OK;
36563dec9fcdSqs 
36573dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type"));
36583dec9fcdSqs 
36593dec9fcdSqs 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
36603dec9fcdSqs 
36613dec9fcdSqs 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
36623dec9fcdSqs 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
36633dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
36643dec9fcdSqs 		    "ddi_intr_get_nintrs() failed, status: 0x%x%, "
36653dec9fcdSqs 		    "nintrs: %d", ddi_status, nintrs));
36663dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
36673dec9fcdSqs 	}
36683dec9fcdSqs 
36693dec9fcdSqs 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
36703dec9fcdSqs 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
36713dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
36723dec9fcdSqs 		    "ddi_intr_get_navail() failed, status: 0x%x%, "
36733dec9fcdSqs 		    "nintrs: %d", ddi_status, navail));
36743dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
36753dec9fcdSqs 	}
36763dec9fcdSqs 
36773dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
36783dec9fcdSqs 	    "ddi_intr_get_navail() returned: intr type %d nintrs %d, navail %d",
36793dec9fcdSqs 	    int_type, nintrs, navail));
36803dec9fcdSqs 
36813dec9fcdSqs 	if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) {
36823dec9fcdSqs 		/* MSI must be power of 2 */
36833dec9fcdSqs 		if ((navail & 16) == 16) {
36843dec9fcdSqs 			navail = 16;
36853dec9fcdSqs 		} else if ((navail & 8) == 8) {
36863dec9fcdSqs 			navail = 8;
36873dec9fcdSqs 		} else if ((navail & 4) == 4) {
36883dec9fcdSqs 			navail = 4;
36893dec9fcdSqs 		} else if ((navail & 2) == 2) {
36903dec9fcdSqs 			navail = 2;
36913dec9fcdSqs 		} else {
36923dec9fcdSqs 			navail = 1;
36933dec9fcdSqs 		}
36943dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
36953dec9fcdSqs 		    "ddi_intr_get_navail(): (msi power of 2) nintrs %d, "
36963dec9fcdSqs 		    "navail %d", nintrs, navail));
36973dec9fcdSqs 	}
36983dec9fcdSqs 
36993dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
37003dec9fcdSqs 	    "requesting: intr type %d nintrs %d, navail %d",
37013dec9fcdSqs 	    int_type, nintrs, navail));
37023dec9fcdSqs 
37033dec9fcdSqs 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
37043dec9fcdSqs 	    DDI_INTR_ALLOC_NORMAL);
37053dec9fcdSqs 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
37063dec9fcdSqs 	intrp->htable = kmem_zalloc(intrp->intr_size, KM_SLEEP);
37073dec9fcdSqs 
37083dec9fcdSqs 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
37093dec9fcdSqs 	    navail, &nactual, behavior);
37103dec9fcdSqs 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
37113dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
37123dec9fcdSqs 		    " ddi_intr_alloc() failed: %d", ddi_status));
37133dec9fcdSqs 		kmem_free(intrp->htable, intrp->intr_size);
37143dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
37153dec9fcdSqs 	}
37163dec9fcdSqs 
37173dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
37183dec9fcdSqs 	    "ddi_intr_alloc() returned: navail %d nactual %d",
37193dec9fcdSqs 	    navail, nactual));
37203dec9fcdSqs 
37213dec9fcdSqs 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
37223dec9fcdSqs 	    (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
37233dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
37243dec9fcdSqs 		    " ddi_intr_get_pri() failed: %d", ddi_status));
37253dec9fcdSqs 		/* Free already allocated interrupts */
37263dec9fcdSqs 		for (y = 0; y < nactual; y++) {
37273dec9fcdSqs 			(void) ddi_intr_free(intrp->htable[y]);
37283dec9fcdSqs 		}
37293dec9fcdSqs 
37303dec9fcdSqs 		kmem_free(intrp->htable, intrp->intr_size);
37313dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
37323dec9fcdSqs 	}
37333dec9fcdSqs 
37343dec9fcdSqs 	nrequired = 0;
37353dec9fcdSqs 	status = hxge_ldgv_init(hxgep, &nactual, &nrequired);
37363dec9fcdSqs 	if (status != HXGE_OK) {
37373dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
37383dec9fcdSqs 		    "hxge_add_intrs_adv_typ:hxge_ldgv_init "
37393dec9fcdSqs 		    "failed: 0x%x", status));
37403dec9fcdSqs 		/* Free already allocated interrupts */
37413dec9fcdSqs 		for (y = 0; y < nactual; y++) {
37423dec9fcdSqs 			(void) ddi_intr_free(intrp->htable[y]);
37433dec9fcdSqs 		}
37443dec9fcdSqs 
37453dec9fcdSqs 		kmem_free(intrp->htable, intrp->intr_size);
37463dec9fcdSqs 		return (status);
37473dec9fcdSqs 	}
37483dec9fcdSqs 
37493dec9fcdSqs 	ldgp = hxgep->ldgvp->ldgp;
37503dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
37513dec9fcdSqs 	    "After hxge_ldgv_init(): nreq %d nactual %d", nrequired, nactual));
37523dec9fcdSqs 
37533dec9fcdSqs 	if (nactual < nrequired)
37543dec9fcdSqs 		loop = nactual;
37553dec9fcdSqs 	else
37563dec9fcdSqs 		loop = nrequired;
37573dec9fcdSqs 
37583dec9fcdSqs 	for (x = 0; x < loop; x++, ldgp++) {
37593dec9fcdSqs 		ldgp->vector = (uint8_t)x;
37603dec9fcdSqs 		arg1 = ldgp->ldvp;
37613dec9fcdSqs 		arg2 = hxgep;
37623dec9fcdSqs 		if (ldgp->nldvs == 1) {
37633dec9fcdSqs 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
37643dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
37653dec9fcdSqs 			    "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: "
37663dec9fcdSqs 			    "1-1 int handler (entry %d)\n",
37673dec9fcdSqs 			    arg1, arg2, x));
37683dec9fcdSqs 		} else if (ldgp->nldvs > 1) {
37693dec9fcdSqs 			inthandler = (uint_t *)ldgp->sys_intr_handler;
37703dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
37713dec9fcdSqs 			    "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: "
37723dec9fcdSqs 			    "nldevs %d int handler (entry %d)\n",
37733dec9fcdSqs 			    arg1, arg2, ldgp->nldvs, x));
37743dec9fcdSqs 		}
37753dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
37763dec9fcdSqs 		    "==> hxge_add_intrs_adv_type: ddi_add_intr(inum) #%d "
37773dec9fcdSqs 		    "htable 0x%llx", x, intrp->htable[x]));
37783dec9fcdSqs 
37793dec9fcdSqs 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
37803dec9fcdSqs 		    (ddi_intr_handler_t *)inthandler, arg1, arg2)) !=
37813dec9fcdSqs 		    DDI_SUCCESS) {
37823dec9fcdSqs 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
37833dec9fcdSqs 			    "==> hxge_add_intrs_adv_type: failed #%d "
37843dec9fcdSqs 			    "status 0x%x", x, ddi_status));
37853dec9fcdSqs 			for (y = 0; y < intrp->intr_added; y++) {
37863dec9fcdSqs 				(void) ddi_intr_remove_handler(
37873dec9fcdSqs 				    intrp->htable[y]);
37883dec9fcdSqs 			}
37893dec9fcdSqs 
37903dec9fcdSqs 			/* Free already allocated intr */
37913dec9fcdSqs 			for (y = 0; y < nactual; y++) {
37923dec9fcdSqs 				(void) ddi_intr_free(intrp->htable[y]);
37933dec9fcdSqs 			}
37943dec9fcdSqs 			kmem_free(intrp->htable, intrp->intr_size);
37953dec9fcdSqs 
37963dec9fcdSqs 			(void) hxge_ldgv_uninit(hxgep);
37973dec9fcdSqs 
37983dec9fcdSqs 			return (HXGE_ERROR | HXGE_DDI_FAILED);
37993dec9fcdSqs 		}
38003dec9fcdSqs 
38013dec9fcdSqs 		intrp->intr_added++;
38023dec9fcdSqs 	}
38033dec9fcdSqs 	intrp->msi_intx_cnt = nactual;
38043dec9fcdSqs 
38053dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
38063dec9fcdSqs 	    "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d",
38073dec9fcdSqs 	    navail, nactual, intrp->msi_intx_cnt, intrp->intr_added));
38083dec9fcdSqs 
38093dec9fcdSqs 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
38103dec9fcdSqs 	(void) hxge_intr_ldgv_init(hxgep);
38113dec9fcdSqs 
38123dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type"));
38133dec9fcdSqs 
38143dec9fcdSqs 	return (status);
38153dec9fcdSqs }
38163dec9fcdSqs 
38173dec9fcdSqs /*ARGSUSED*/
38183dec9fcdSqs static hxge_status_t
38193dec9fcdSqs hxge_add_intrs_adv_type_fix(p_hxge_t hxgep, uint32_t int_type)
38203dec9fcdSqs {
38213dec9fcdSqs 	dev_info_t	*dip = hxgep->dip;
38223dec9fcdSqs 	p_hxge_ldg_t	ldgp;
38233dec9fcdSqs 	p_hxge_intr_t	intrp;
38243dec9fcdSqs 	uint_t		*inthandler;
38253dec9fcdSqs 	void		*arg1, *arg2;
38263dec9fcdSqs 	int		behavior;
38273dec9fcdSqs 	int		nintrs, navail;
38283dec9fcdSqs 	int		nactual, nrequired;
38293dec9fcdSqs 	int		inum = 0;
38303dec9fcdSqs 	int		x, y;
38313dec9fcdSqs 	int		ddi_status = DDI_SUCCESS;
38323dec9fcdSqs 	hxge_status_t	status = HXGE_OK;
38333dec9fcdSqs 
38343dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type_fix"));
38353dec9fcdSqs 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
38363dec9fcdSqs 
38373dec9fcdSqs 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
38383dec9fcdSqs 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
38393dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
38403dec9fcdSqs 		    "ddi_intr_get_nintrs() failed, status: 0x%x%, "
38413dec9fcdSqs 		    "nintrs: %d", status, nintrs));
38423dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
38433dec9fcdSqs 	}
38443dec9fcdSqs 
38453dec9fcdSqs 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
38463dec9fcdSqs 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
38473dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38483dec9fcdSqs 		    "ddi_intr_get_navail() failed, status: 0x%x%, "
38493dec9fcdSqs 		    "nintrs: %d", ddi_status, navail));
38503dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
38513dec9fcdSqs 	}
38523dec9fcdSqs 
38533dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
38543dec9fcdSqs 	    "ddi_intr_get_navail() returned: nintrs %d, naavail %d",
38553dec9fcdSqs 	    nintrs, navail));
38563dec9fcdSqs 
38573dec9fcdSqs 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
38583dec9fcdSqs 	    DDI_INTR_ALLOC_NORMAL);
38593dec9fcdSqs 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
38603dec9fcdSqs 	intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
38613dec9fcdSqs 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
38623dec9fcdSqs 	    navail, &nactual, behavior);
38633dec9fcdSqs 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
38643dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38653dec9fcdSqs 		    " ddi_intr_alloc() failed: %d", ddi_status));
38663dec9fcdSqs 		kmem_free(intrp->htable, intrp->intr_size);
38673dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
38683dec9fcdSqs 	}
38693dec9fcdSqs 
38703dec9fcdSqs 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
38713dec9fcdSqs 	    (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
38723dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38733dec9fcdSqs 		    " ddi_intr_get_pri() failed: %d", ddi_status));
38743dec9fcdSqs 		/* Free already allocated interrupts */
38753dec9fcdSqs 		for (y = 0; y < nactual; y++) {
38763dec9fcdSqs 			(void) ddi_intr_free(intrp->htable[y]);
38773dec9fcdSqs 		}
38783dec9fcdSqs 
38793dec9fcdSqs 		kmem_free(intrp->htable, intrp->intr_size);
38803dec9fcdSqs 		return (HXGE_ERROR | HXGE_DDI_FAILED);
38813dec9fcdSqs 	}
38823dec9fcdSqs 
38833dec9fcdSqs 	nrequired = 0;
38843dec9fcdSqs 	status = hxge_ldgv_init(hxgep, &nactual, &nrequired);
38853dec9fcdSqs 	if (status != HXGE_OK) {
38863dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
38873dec9fcdSqs 		    "hxge_add_intrs_adv_type_fix:hxge_ldgv_init "
38883dec9fcdSqs 		    "failed: 0x%x", status));
38893dec9fcdSqs 		/* Free already allocated interrupts */
38903dec9fcdSqs 		for (y = 0; y < nactual; y++) {
38913dec9fcdSqs 			(void) ddi_intr_free(intrp->htable[y]);
38923dec9fcdSqs 		}
38933dec9fcdSqs 
38943dec9fcdSqs 		kmem_free(intrp->htable, intrp->intr_size);
38953dec9fcdSqs 		return (status);
38963dec9fcdSqs 	}
38973dec9fcdSqs 
38983dec9fcdSqs 	ldgp = hxgep->ldgvp->ldgp;
38993dec9fcdSqs 	for (x = 0; x < nrequired; x++, ldgp++) {
39003dec9fcdSqs 		ldgp->vector = (uint8_t)x;
39013dec9fcdSqs 		arg1 = ldgp->ldvp;
39023dec9fcdSqs 		arg2 = hxgep;
39033dec9fcdSqs 		if (ldgp->nldvs == 1) {
39043dec9fcdSqs 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
39053dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
39063dec9fcdSqs 			    "hxge_add_intrs_adv_type_fix: "
39073dec9fcdSqs 			    "1-1 int handler(%d) ldg %d ldv %d "
39083dec9fcdSqs 			    "arg1 $%p arg2 $%p\n",
39093dec9fcdSqs 			    x, ldgp->ldg, ldgp->ldvp->ldv, arg1, arg2));
39103dec9fcdSqs 		} else if (ldgp->nldvs > 1) {
39113dec9fcdSqs 			inthandler = (uint_t *)ldgp->sys_intr_handler;
39123dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
39133dec9fcdSqs 			    "hxge_add_intrs_adv_type_fix: "
39143dec9fcdSqs 			    "shared ldv %d int handler(%d) ldv %d ldg %d"
39153dec9fcdSqs 			    "arg1 0x%016llx arg2 0x%016llx\n",
39163dec9fcdSqs 			    x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv,
39173dec9fcdSqs 			    arg1, arg2));
39183dec9fcdSqs 		}
39193dec9fcdSqs 
39203dec9fcdSqs 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
39213dec9fcdSqs 		    (ddi_intr_handler_t *)inthandler, arg1, arg2)) !=
39223dec9fcdSqs 		    DDI_SUCCESS) {
39233dec9fcdSqs 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
39243dec9fcdSqs 			    "==> hxge_add_intrs_adv_type_fix: failed #%d "
39253dec9fcdSqs 			    "status 0x%x", x, ddi_status));
39263dec9fcdSqs 			for (y = 0; y < intrp->intr_added; y++) {
39273dec9fcdSqs 				(void) ddi_intr_remove_handler(
39283dec9fcdSqs 				    intrp->htable[y]);
39293dec9fcdSqs 			}
39303dec9fcdSqs 			for (y = 0; y < nactual; y++) {
39313dec9fcdSqs 				(void) ddi_intr_free(intrp->htable[y]);
39323dec9fcdSqs 			}
39333dec9fcdSqs 			/* Free already allocated intr */
39343dec9fcdSqs 			kmem_free(intrp->htable, intrp->intr_size);
39353dec9fcdSqs 
39363dec9fcdSqs 			(void) hxge_ldgv_uninit(hxgep);
39373dec9fcdSqs 
39383dec9fcdSqs 			return (HXGE_ERROR | HXGE_DDI_FAILED);
39393dec9fcdSqs 		}
39403dec9fcdSqs 		intrp->intr_added++;
39413dec9fcdSqs 	}
39423dec9fcdSqs 
39433dec9fcdSqs 	intrp->msi_intx_cnt = nactual;
39443dec9fcdSqs 
39453dec9fcdSqs 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
39463dec9fcdSqs 
39473dec9fcdSqs 	status = hxge_intr_ldgv_init(hxgep);
39483dec9fcdSqs 
39493dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type_fix"));
39503dec9fcdSqs 
39513dec9fcdSqs 	return (status);
39523dec9fcdSqs }
39533dec9fcdSqs 
39543dec9fcdSqs /*ARGSUSED*/
39553dec9fcdSqs static void
39563dec9fcdSqs hxge_remove_intrs(p_hxge_t hxgep)
39573dec9fcdSqs {
39583dec9fcdSqs 	int		i, inum;
39593dec9fcdSqs 	p_hxge_intr_t	intrp;
39603dec9fcdSqs 
39613dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs"));
39623dec9fcdSqs 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
39633dec9fcdSqs 	if (!intrp->intr_registered) {
39643dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
39653dec9fcdSqs 		    "<== hxge_remove_intrs: interrupts not registered"));
39663dec9fcdSqs 		return;
39673dec9fcdSqs 	}
39683dec9fcdSqs 
39693dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs:advanced"));
39703dec9fcdSqs 
39713dec9fcdSqs 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
39723dec9fcdSqs 		(void) ddi_intr_block_disable(intrp->htable,
39733dec9fcdSqs 		    intrp->intr_added);
39743dec9fcdSqs 	} else {
39753dec9fcdSqs 		for (i = 0; i < intrp->intr_added; i++) {
39763dec9fcdSqs 			(void) ddi_intr_disable(intrp->htable[i]);
39773dec9fcdSqs 		}
39783dec9fcdSqs 	}
39793dec9fcdSqs 
39803dec9fcdSqs 	for (inum = 0; inum < intrp->intr_added; inum++) {
39813dec9fcdSqs 		if (intrp->htable[inum]) {
39823dec9fcdSqs 			(void) ddi_intr_remove_handler(intrp->htable[inum]);
39833dec9fcdSqs 		}
39843dec9fcdSqs 	}
39853dec9fcdSqs 
39863dec9fcdSqs 	for (inum = 0; inum < intrp->msi_intx_cnt; inum++) {
39873dec9fcdSqs 		if (intrp->htable[inum]) {
39883dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
39893dec9fcdSqs 			    "hxge_remove_intrs: ddi_intr_free inum %d "
39903dec9fcdSqs 			    "msi_intx_cnt %d intr_added %d",
39913dec9fcdSqs 			    inum, intrp->msi_intx_cnt, intrp->intr_added));
39923dec9fcdSqs 
39933dec9fcdSqs 			(void) ddi_intr_free(intrp->htable[inum]);
39943dec9fcdSqs 		}
39953dec9fcdSqs 	}
39963dec9fcdSqs 
39973dec9fcdSqs 	kmem_free(intrp->htable, intrp->intr_size);
39983dec9fcdSqs 	intrp->intr_registered = B_FALSE;
39993dec9fcdSqs 	intrp->intr_enabled = B_FALSE;
40003dec9fcdSqs 	intrp->msi_intx_cnt = 0;
40013dec9fcdSqs 	intrp->intr_added = 0;
40023dec9fcdSqs 
40033dec9fcdSqs 	(void) hxge_ldgv_uninit(hxgep);
40043dec9fcdSqs 
40053dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_intrs"));
40063dec9fcdSqs }
40073dec9fcdSqs 
40083dec9fcdSqs /*ARGSUSED*/
40093dec9fcdSqs static void
40103dec9fcdSqs hxge_remove_soft_intrs(p_hxge_t hxgep)
40113dec9fcdSqs {
40123dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_soft_intrs"));
40133dec9fcdSqs 
40143dec9fcdSqs 	if (hxgep->resched_id) {
40153dec9fcdSqs 		ddi_remove_softintr(hxgep->resched_id);
40163dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
40173dec9fcdSqs 		    "==> hxge_remove_soft_intrs: removed"));
40183dec9fcdSqs 		hxgep->resched_id = NULL;
40193dec9fcdSqs 	}
40203dec9fcdSqs 
40213dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_soft_intrs"));
40223dec9fcdSqs }
40233dec9fcdSqs 
40243dec9fcdSqs /*ARGSUSED*/
40253dec9fcdSqs void
40263dec9fcdSqs hxge_intrs_enable(p_hxge_t hxgep)
40273dec9fcdSqs {
40283dec9fcdSqs 	p_hxge_intr_t	intrp;
40293dec9fcdSqs 	int		i;
40303dec9fcdSqs 	int		status;
40313dec9fcdSqs 
40323dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable"));
40333dec9fcdSqs 
40343dec9fcdSqs 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
40353dec9fcdSqs 
40363dec9fcdSqs 	if (!intrp->intr_registered) {
40373dec9fcdSqs 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_intrs_enable: "
40383dec9fcdSqs 		    "interrupts are not registered"));
40393dec9fcdSqs 		return;
40403dec9fcdSqs 	}
40413dec9fcdSqs 
40423dec9fcdSqs 	if (intrp->intr_enabled) {
40433dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
40443dec9fcdSqs 		    "<== hxge_intrs_enable: already enabled"));
40453dec9fcdSqs 		return;
40463dec9fcdSqs 	}
40473dec9fcdSqs 
40483dec9fcdSqs 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
40493dec9fcdSqs 		status = ddi_intr_block_enable(intrp->htable,
40503dec9fcdSqs 		    intrp->intr_added);
40513dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable "
40523dec9fcdSqs 		    "block enable - status 0x%x total inums #%d\n",
40533dec9fcdSqs 		    status, intrp->intr_added));
40543dec9fcdSqs 	} else {
40553dec9fcdSqs 		for (i = 0; i < intrp->intr_added; i++) {
40563dec9fcdSqs 			status = ddi_intr_enable(intrp->htable[i]);
40573dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable "
40583dec9fcdSqs 			    "ddi_intr_enable:enable - status 0x%x "
40593dec9fcdSqs 			    "total inums %d enable inum #%d\n",
40603dec9fcdSqs 			    status, intrp->intr_added, i));
40613dec9fcdSqs 			if (status == DDI_SUCCESS) {
40623dec9fcdSqs 				intrp->intr_enabled = B_TRUE;
40633dec9fcdSqs 			}
40643dec9fcdSqs 		}
40653dec9fcdSqs 	}
40663dec9fcdSqs 
40673dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_enable"));
40683dec9fcdSqs }
40693dec9fcdSqs 
40703dec9fcdSqs /*ARGSUSED*/
40713dec9fcdSqs static void
40723dec9fcdSqs hxge_intrs_disable(p_hxge_t hxgep)
40733dec9fcdSqs {
40743dec9fcdSqs 	p_hxge_intr_t	intrp;
40753dec9fcdSqs 	int		i;
40763dec9fcdSqs 
40773dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_disable"));
40783dec9fcdSqs 
40793dec9fcdSqs 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
40803dec9fcdSqs 
40813dec9fcdSqs 	if (!intrp->intr_registered) {
40823dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable: "
40833dec9fcdSqs 		    "interrupts are not registered"));
40843dec9fcdSqs 		return;
40853dec9fcdSqs 	}
40863dec9fcdSqs 
40873dec9fcdSqs 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
40883dec9fcdSqs 		(void) ddi_intr_block_disable(intrp->htable,
40893dec9fcdSqs 		    intrp->intr_added);
40903dec9fcdSqs 	} else {
40913dec9fcdSqs 		for (i = 0; i < intrp->intr_added; i++) {
40923dec9fcdSqs 			(void) ddi_intr_disable(intrp->htable[i]);
40933dec9fcdSqs 		}
40943dec9fcdSqs 	}
40953dec9fcdSqs 
40963dec9fcdSqs 	intrp->intr_enabled = B_FALSE;
40973dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable"));
40983dec9fcdSqs }
40993dec9fcdSqs 
41003dec9fcdSqs static hxge_status_t
41013dec9fcdSqs hxge_mac_register(p_hxge_t hxgep)
41023dec9fcdSqs {
41033dec9fcdSqs 	mac_register_t	*macp;
41043dec9fcdSqs 	int		status;
41053dec9fcdSqs 
41063dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_mac_register"));
41073dec9fcdSqs 
41083dec9fcdSqs 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
41093dec9fcdSqs 		return (HXGE_ERROR);
41103dec9fcdSqs 
41113dec9fcdSqs 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
41123dec9fcdSqs 	macp->m_driver = hxgep;
41133dec9fcdSqs 	macp->m_dip = hxgep->dip;
41143dec9fcdSqs 	macp->m_src_addr = hxgep->ouraddr.ether_addr_octet;
41153dec9fcdSqs 
41163dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
41173dec9fcdSqs 	    "hxge_mac_register: ether addr is %x:%x:%x:%x:%x:%x",
41183dec9fcdSqs 	    macp->m_src_addr[0],
41193dec9fcdSqs 	    macp->m_src_addr[1],
41203dec9fcdSqs 	    macp->m_src_addr[2],
41213dec9fcdSqs 	    macp->m_src_addr[3],
41223dec9fcdSqs 	    macp->m_src_addr[4],
41233dec9fcdSqs 	    macp->m_src_addr[5]));
41243dec9fcdSqs 
41253dec9fcdSqs 	macp->m_callbacks = &hxge_m_callbacks;
41263dec9fcdSqs 	macp->m_min_sdu = 0;
4127*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	macp->m_max_sdu = hxgep->vmac.maxframesize - MTU_TO_FRAME_SIZE;
4128*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	macp->m_margin = VLAN_TAGSZ;
4129*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	macp->m_priv_props = hxge_priv_props;
4130*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	macp->m_priv_prop_count = HXGE_MAX_PRIV_PROPS;
41313dec9fcdSqs 
41323dec9fcdSqs 	status = mac_register(macp, &hxgep->mach);
41333dec9fcdSqs 	mac_free(macp);
41343dec9fcdSqs 
41353dec9fcdSqs 	if (status != 0) {
41363dec9fcdSqs 		cmn_err(CE_WARN,
41373dec9fcdSqs 		    "hxge_mac_register failed (status %d instance %d)",
41383dec9fcdSqs 		    status, hxgep->instance);
41393dec9fcdSqs 		return (HXGE_ERROR);
41403dec9fcdSqs 	}
41413dec9fcdSqs 
41423dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_mac_register success "
41433dec9fcdSqs 	    "(instance %d)", hxgep->instance));
41443dec9fcdSqs 
41453dec9fcdSqs 	return (HXGE_OK);
41463dec9fcdSqs }
41473dec9fcdSqs 
41483dec9fcdSqs static int
41493dec9fcdSqs hxge_init_common_dev(p_hxge_t hxgep)
41503dec9fcdSqs {
41513dec9fcdSqs 	p_hxge_hw_list_t	hw_p;
41523dec9fcdSqs 	dev_info_t		*p_dip;
41533dec9fcdSqs 
41543dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_init_common_dev"));
41553dec9fcdSqs 
41563dec9fcdSqs 	p_dip = hxgep->p_dip;
41573dec9fcdSqs 	MUTEX_ENTER(&hxge_common_lock);
41583dec9fcdSqs 
41593dec9fcdSqs 	/*
41603dec9fcdSqs 	 * Loop through existing per Hydra hardware list.
41613dec9fcdSqs 	 */
41623dec9fcdSqs 	for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) {
41633dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
41643dec9fcdSqs 		    "==> hxge_init_common_dev: hw_p $%p parent dip $%p",
41653dec9fcdSqs 		    hw_p, p_dip));
41663dec9fcdSqs 		if (hw_p->parent_devp == p_dip) {
41673dec9fcdSqs 			hxgep->hxge_hw_p = hw_p;
41683dec9fcdSqs 			hw_p->ndevs++;
41693dec9fcdSqs 			hw_p->hxge_p = hxgep;
41703dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, MOD_CTL,
41713dec9fcdSqs 			    "==> hxge_init_common_device: "
41723dec9fcdSqs 			    "hw_p $%p parent dip $%p ndevs %d (found)",
41733dec9fcdSqs 			    hw_p, p_dip, hw_p->ndevs));
41743dec9fcdSqs 			break;
41753dec9fcdSqs 		}
41763dec9fcdSqs 	}
41773dec9fcdSqs 
41783dec9fcdSqs 	if (hw_p == NULL) {
41793dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
41803dec9fcdSqs 		    "==> hxge_init_common_dev: parent dip $%p (new)", p_dip));
41813dec9fcdSqs 		hw_p = kmem_zalloc(sizeof (hxge_hw_list_t), KM_SLEEP);
41823dec9fcdSqs 		hw_p->parent_devp = p_dip;
41833dec9fcdSqs 		hw_p->magic = HXGE_MAGIC;
41843dec9fcdSqs 		hxgep->hxge_hw_p = hw_p;
41853dec9fcdSqs 		hw_p->ndevs++;
41863dec9fcdSqs 		hw_p->hxge_p = hxgep;
41873dec9fcdSqs 		hw_p->next = hxge_hw_list;
41883dec9fcdSqs 
41893dec9fcdSqs 		MUTEX_INIT(&hw_p->hxge_cfg_lock, NULL, MUTEX_DRIVER, NULL);
41903dec9fcdSqs 		MUTEX_INIT(&hw_p->hxge_tcam_lock, NULL, MUTEX_DRIVER, NULL);
41913dec9fcdSqs 		MUTEX_INIT(&hw_p->hxge_vlan_lock, NULL, MUTEX_DRIVER, NULL);
41923dec9fcdSqs 
41933dec9fcdSqs 		hxge_hw_list = hw_p;
41943dec9fcdSqs 	}
41953dec9fcdSqs 	MUTEX_EXIT(&hxge_common_lock);
41963dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MOD_CTL,
41973dec9fcdSqs 	    "==> hxge_init_common_dev (hxge_hw_list) $%p", hxge_hw_list));
41983dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<== hxge_init_common_dev"));
41993dec9fcdSqs 
42003dec9fcdSqs 	return (HXGE_OK);
42013dec9fcdSqs }
42023dec9fcdSqs 
42033dec9fcdSqs static void
42043dec9fcdSqs hxge_uninit_common_dev(p_hxge_t hxgep)
42053dec9fcdSqs {
42063dec9fcdSqs 	p_hxge_hw_list_t	hw_p, h_hw_p;
42073dec9fcdSqs 	dev_info_t		*p_dip;
42083dec9fcdSqs 
42093dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_uninit_common_dev"));
42103dec9fcdSqs 	if (hxgep->hxge_hw_p == NULL) {
42113dec9fcdSqs 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
42123dec9fcdSqs 		    "<== hxge_uninit_common_dev (no common)"));
42133dec9fcdSqs 		return;
42143dec9fcdSqs 	}
42153dec9fcdSqs 
42163dec9fcdSqs 	MUTEX_ENTER(&hxge_common_lock);
42173dec9fcdSqs 	h_hw_p = hxge_hw_list;
42183dec9fcdSqs 	for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) {
42193dec9fcdSqs 		p_dip = hw_p->parent_devp;
42203dec9fcdSqs 		if (hxgep->hxge_hw_p == hw_p && p_dip == hxgep->p_dip &&
42213dec9fcdSqs 		    hxgep->hxge_hw_p->magic == HXGE_MAGIC &&
42223dec9fcdSqs 		    hw_p->magic == HXGE_MAGIC) {
42233dec9fcdSqs 			HXGE_DEBUG_MSG((hxgep, MOD_CTL,
42243dec9fcdSqs 			    "==> hxge_uninit_common_dev: "
42253dec9fcdSqs 			    "hw_p $%p parent dip $%p ndevs %d (found)",
42263dec9fcdSqs 			    hw_p, p_dip, hw_p->ndevs));
42273dec9fcdSqs 
42283dec9fcdSqs 			hxgep->hxge_hw_p = NULL;
42293dec9fcdSqs 			if (hw_p->ndevs) {
42303dec9fcdSqs 				hw_p->ndevs--;
42313dec9fcdSqs 			}
42323dec9fcdSqs 			hw_p->hxge_p = NULL;
42333dec9fcdSqs 			if (!hw_p->ndevs) {
42343dec9fcdSqs 				MUTEX_DESTROY(&hw_p->hxge_vlan_lock);
42353dec9fcdSqs 				MUTEX_DESTROY(&hw_p->hxge_tcam_lock);
42363dec9fcdSqs 				MUTEX_DESTROY(&hw_p->hxge_cfg_lock);
42373dec9fcdSqs 				HXGE_DEBUG_MSG((hxgep, MOD_CTL,
42383dec9fcdSqs 				    "==> hxge_uninit_common_dev: "
42393dec9fcdSqs 				    "hw_p $%p parent dip $%p ndevs %d (last)",
42403dec9fcdSqs 				    hw_p, p_dip, hw_p->ndevs));
42413dec9fcdSqs 
42423dec9fcdSqs 				if (hw_p == hxge_hw_list) {
42433dec9fcdSqs 					HXGE_DEBUG_MSG((hxgep, MOD_CTL,
42443dec9fcdSqs 					    "==> hxge_uninit_common_dev:"
42453dec9fcdSqs 					    "remove head "
42463dec9fcdSqs 					    "hw_p $%p parent dip $%p "
42473dec9fcdSqs 					    "ndevs %d (head)",
42483dec9fcdSqs 					    hw_p, p_dip, hw_p->ndevs));
42493dec9fcdSqs 					hxge_hw_list = hw_p->next;
42503dec9fcdSqs 				} else {
42513dec9fcdSqs 					HXGE_DEBUG_MSG((hxgep, MOD_CTL,
42523dec9fcdSqs 					    "==> hxge_uninit_common_dev:"
42533dec9fcdSqs 					    "remove middle "
42543dec9fcdSqs 					    "hw_p $%p parent dip $%p "
42553dec9fcdSqs 					    "ndevs %d (middle)",
42563dec9fcdSqs 					    hw_p, p_dip, hw_p->ndevs));
42573dec9fcdSqs 					h_hw_p->next = hw_p->next;
42583dec9fcdSqs 				}
42593dec9fcdSqs 
42603dec9fcdSqs 				KMEM_FREE(hw_p, sizeof (hxge_hw_list_t));
42613dec9fcdSqs 			}
42623dec9fcdSqs 			break;
42633dec9fcdSqs 		} else {
42643dec9fcdSqs 			h_hw_p = hw_p;
42653dec9fcdSqs 		}
42663dec9fcdSqs 	}
42673dec9fcdSqs 
42683dec9fcdSqs 	MUTEX_EXIT(&hxge_common_lock);
42693dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MOD_CTL,
42703dec9fcdSqs 	    "==> hxge_uninit_common_dev (hxge_hw_list) $%p", hxge_hw_list));
42713dec9fcdSqs 
42723dec9fcdSqs 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<= hxge_uninit_common_dev"));
42733dec9fcdSqs }
4274*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
4275*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States static void
4276*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States hxge_link_poll(void *arg)
4277*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States {
4278*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	p_hxge_t		hxgep = (p_hxge_t)arg;
4279*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hpi_handle_t		handle;
4280*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	p_hxge_stats_t		statsp;
4281*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	cip_link_stat_t		link_stat;
4282*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	hxge_timeout		*to = &hxgep->timeout;
4283*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
4284*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	handle = HXGE_DEV_HPI_HANDLE(hxgep);
4285*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	statsp = (p_hxge_stats_t)hxgep->statsp;
4286*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	HXGE_REG_RD32(handle, CIP_LINK_STAT, &link_stat.value);
4287*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
4288*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	if (to->link_status != link_stat.bits.xpcs0_link_up) {
4289*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		to->link_status = link_stat.bits.xpcs0_link_up;
4290*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
4291*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		if (link_stat.bits.xpcs0_link_up) {
4292*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			mac_link_update(hxgep->mach, LINK_STATE_UP);
4293*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			statsp->mac_stats.link_speed = 10000;
4294*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			statsp->mac_stats.link_duplex = 2;
4295*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			statsp->mac_stats.link_up = 1;
4296*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		} else {
4297*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			mac_link_update(hxgep->mach, LINK_STATE_DOWN);
4298*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			statsp->mac_stats.link_speed = 0;
4299*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			statsp->mac_stats.link_duplex = 0;
4300*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 			statsp->mac_stats.link_up = 0;
4301*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 		}
4302*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	}
4303*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 
4304*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	/* Restart the link status timer to check the link status */
4305*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_ENTER(&to->lock);
4306*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	to->id = timeout(hxge_link_poll, arg, to->ticks);
4307*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 	MUTEX_EXIT(&to->lock);
4308*a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States }
4309