xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_hw.c (revision 5060:222c7d448cfc)
13859Sml29623 /*
23859Sml29623  * CDDL HEADER START
33859Sml29623  *
43859Sml29623  * The contents of this file are subject to the terms of the
53859Sml29623  * Common Development and Distribution License (the "License").
63859Sml29623  * You may not use this file except in compliance with the License.
73859Sml29623  *
83859Sml29623  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93859Sml29623  * or http://www.opensolaris.org/os/licensing.
103859Sml29623  * See the License for the specific language governing permissions
113859Sml29623  * and limitations under the License.
123859Sml29623  *
133859Sml29623  * When distributing Covered Code, include this CDDL HEADER in each
143859Sml29623  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153859Sml29623  * If applicable, add the following below this CDDL HEADER, with the
163859Sml29623  * fields enclosed by brackets "[]" replaced with your own identifying
173859Sml29623  * information: Portions Copyright [yyyy] [name of copyright owner]
183859Sml29623  *
193859Sml29623  * CDDL HEADER END
203859Sml29623  */
213859Sml29623 /*
223859Sml29623  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
233859Sml29623  * Use is subject to license terms.
243859Sml29623  */
253859Sml29623 
263859Sml29623 #pragma ident	"%Z%%M%	%I%	%E% SMI"
273859Sml29623 
283859Sml29623 #include <sys/nxge/nxge_impl.h>
293859Sml29623 
303859Sml29623 /*
313859Sml29623  * Tunable Receive Completion Ring Configuration B parameters.
323859Sml29623  */
333859Sml29623 uint16_t nxge_rx_pkt_thres;	/* 16 bits */
343859Sml29623 uint8_t nxge_rx_pkt_timeout;	/* 6 bits based on DMA clock divider */
353859Sml29623 
363859Sml29623 lb_property_t lb_normal = {normal, "normal", nxge_lb_normal};
373859Sml29623 lb_property_t lb_external10g = {external, "external10g", nxge_lb_ext10g};
383859Sml29623 lb_property_t lb_external1000 = {external, "external1000", nxge_lb_ext1000};
393859Sml29623 lb_property_t lb_external100 = {external, "external100", nxge_lb_ext100};
403859Sml29623 lb_property_t lb_external10 = {external, "external10", nxge_lb_ext10};
413859Sml29623 lb_property_t lb_phy10g = {internal, "phy10g", nxge_lb_phy10g};
423859Sml29623 lb_property_t lb_phy1000 = {internal, "phy1000", nxge_lb_phy1000};
433859Sml29623 lb_property_t lb_phy = {internal, "phy", nxge_lb_phy};
443859Sml29623 lb_property_t lb_serdes10g = {internal, "serdes10g", nxge_lb_serdes10g};
453859Sml29623 lb_property_t lb_serdes1000 = {internal, "serdes", nxge_lb_serdes1000};
463859Sml29623 lb_property_t lb_mac10g = {internal, "mac10g", nxge_lb_mac10g};
473859Sml29623 lb_property_t lb_mac1000 = {internal, "mac1000", nxge_lb_mac1000};
483859Sml29623 lb_property_t lb_mac = {internal, "mac10/100", nxge_lb_mac};
493859Sml29623 
503859Sml29623 uint32_t nxge_lb_dbg = 1;
513859Sml29623 void nxge_get_mii(p_nxge_t nxgep, p_mblk_t mp);
523859Sml29623 void nxge_put_mii(p_nxge_t nxgep, p_mblk_t mp);
53*5060Syc148097 static nxge_status_t nxge_check_xaui_xfp(p_nxge_t nxgep);
543859Sml29623 
553859Sml29623 extern uint32_t nxge_rx_mode;
563859Sml29623 extern uint32_t nxge_jumbo_mtu;
573859Sml29623 extern boolean_t nxge_jumbo_enable;
583859Sml29623 
593859Sml29623 static void
603859Sml29623 nxge_rtrace_ioctl(p_nxge_t, queue_t *, mblk_t *, struct iocblk *);
613859Sml29623 
623859Sml29623 /* ARGSUSED */
633859Sml29623 void
643859Sml29623 nxge_global_reset(p_nxge_t nxgep)
653859Sml29623 {
663859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_global_reset"));
673859Sml29623 
683859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
693859Sml29623 	(void) nxge_intr_hw_disable(nxgep);
703859Sml29623 
713859Sml29623 	if ((nxgep->suspended) ||
723859Sml29623 			((nxgep->statsp->port_stats.lb_mode ==
733859Sml29623 			nxge_lb_phy1000) ||
743859Sml29623 			(nxgep->statsp->port_stats.lb_mode ==
753859Sml29623 			nxge_lb_phy10g) ||
763859Sml29623 			(nxgep->statsp->port_stats.lb_mode ==
773859Sml29623 			nxge_lb_serdes1000) ||
783859Sml29623 			(nxgep->statsp->port_stats.lb_mode ==
793859Sml29623 			nxge_lb_serdes10g))) {
803859Sml29623 		(void) nxge_link_init(nxgep);
813859Sml29623 	}
823859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
833859Sml29623 	(void) nxge_mac_init(nxgep);
843859Sml29623 	(void) nxge_intr_hw_enable(nxgep);
853859Sml29623 
863859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_global_reset"));
873859Sml29623 }
883859Sml29623 
893859Sml29623 /* ARGSUSED */
903859Sml29623 void
913859Sml29623 nxge_hw_id_init(p_nxge_t nxgep)
923859Sml29623 {
933859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_id_init"));
943859Sml29623 	/*
953859Sml29623 	 * Set up initial hardware parameters required such as mac mtu size.
963859Sml29623 	 */
973859Sml29623 	nxgep->mac.is_jumbo = B_FALSE;
983859Sml29623 	nxgep->mac.maxframesize = NXGE_MTU_DEFAULT_MAX;	/* 1522 */
993859Sml29623 	if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
1003859Sml29623 		nxgep->mac.maxframesize = (uint16_t)nxge_jumbo_mtu;
1013859Sml29623 		nxgep->mac.is_jumbo = B_TRUE;
1023859Sml29623 	}
1033859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1043859Sml29623 		"==> nxge_hw_id_init: maxframesize %d",
1053859Sml29623 		nxgep->mac.maxframesize));
1063859Sml29623 
1073859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_id_init"));
1083859Sml29623 }
1093859Sml29623 
1103859Sml29623 /* ARGSUSED */
1113859Sml29623 void
1123859Sml29623 nxge_hw_init_niu_common(p_nxge_t nxgep)
1133859Sml29623 {
1143859Sml29623 	p_nxge_hw_list_t hw_p;
1153859Sml29623 
1163859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_init_niu_common"));
1173859Sml29623 
1183859Sml29623 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
1193859Sml29623 		return;
1203859Sml29623 	}
1213859Sml29623 	MUTEX_ENTER(&hw_p->nxge_cfg_lock);
1223859Sml29623 	if (hw_p->flags & COMMON_INIT_DONE) {
1233859Sml29623 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
1243859Sml29623 			"nxge_hw_init_niu_common"
1253859Sml29623 			" already done for dip $%p function %d exiting",
1263859Sml29623 			hw_p->parent_devp, nxgep->function_num));
1273859Sml29623 		MUTEX_EXIT(&hw_p->nxge_cfg_lock);
1283859Sml29623 		return;
1293859Sml29623 	}
1303859Sml29623 
1313859Sml29623 	hw_p->flags = COMMON_INIT_START;
1323859Sml29623 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxge_hw_init_niu_common"
1333859Sml29623 		" Started for device id %x with function %d",
1343859Sml29623 		hw_p->parent_devp, nxgep->function_num));
1353859Sml29623 
1363859Sml29623 	/* per neptune common block init */
1373859Sml29623 	(void) nxge_fflp_hw_reset(nxgep);
1383859Sml29623 
1393859Sml29623 	hw_p->flags = COMMON_INIT_DONE;
1403859Sml29623 	MUTEX_EXIT(&hw_p->nxge_cfg_lock);
1413859Sml29623 
1423859Sml29623 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxge_hw_init_niu_common"
1433859Sml29623 		" Done for device id %x with function %d",
1443859Sml29623 		hw_p->parent_devp, nxgep->function_num));
1453859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_init_niu_common"));
1463859Sml29623 }
1473859Sml29623 
1483859Sml29623 /* ARGSUSED */
1493859Sml29623 uint_t
1503859Sml29623 nxge_intr(void *arg1, void *arg2)
1513859Sml29623 {
1523859Sml29623 	p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
1533859Sml29623 	p_nxge_t nxgep = (p_nxge_t)arg2;
1543859Sml29623 	uint_t serviced = DDI_INTR_UNCLAIMED;
1553859Sml29623 	uint8_t ldv;
1563859Sml29623 	npi_handle_t handle;
1573859Sml29623 	p_nxge_ldgv_t ldgvp;
1583859Sml29623 	p_nxge_ldg_t ldgp, t_ldgp;
1593859Sml29623 	p_nxge_ldv_t t_ldvp;
1603859Sml29623 	uint64_t vector0 = 0, vector1 = 0, vector2 = 0;
1613859Sml29623 	int i, j, nldvs, nintrs = 1;
1623859Sml29623 	npi_status_t rs = NPI_SUCCESS;
1633859Sml29623 
1643859Sml29623 	/* DDI interface returns second arg as NULL (n2 niumx driver) !!! */
1653859Sml29623 	if (arg2 == NULL || (void *) ldvp->nxgep != arg2) {
1663859Sml29623 		nxgep = ldvp->nxgep;
1673859Sml29623 	}
1683859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr"));
1693859Sml29623 
1703859Sml29623 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
1713859Sml29623 		NXGE_ERROR_MSG((nxgep, INT_CTL,
1723859Sml29623 			"<== nxge_intr: not initialized 0x%x", serviced));
1733859Sml29623 		return (serviced);
1743859Sml29623 	}
1753859Sml29623 
1763859Sml29623 	ldgvp = nxgep->ldgvp;
1773859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: ldgvp $%p", ldgvp));
1783859Sml29623 	if (ldvp == NULL && ldgvp) {
1793859Sml29623 		t_ldvp = ldvp = ldgvp->ldvp;
1803859Sml29623 	}
1813859Sml29623 	if (ldvp) {
1823859Sml29623 		ldgp = t_ldgp = ldvp->ldgp;
1833859Sml29623 	}
1843859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: "
1853859Sml29623 		"ldgvp $%p ldvp $%p ldgp $%p", ldgvp, ldvp, ldgp));
1863859Sml29623 	if (ldgvp == NULL || ldvp == NULL || ldgp == NULL) {
1873859Sml29623 		NXGE_ERROR_MSG((nxgep, INT_CTL, "==> nxge_intr: "
1883859Sml29623 			"ldgvp $%p ldvp $%p ldgp $%p", ldgvp, ldvp, ldgp));
1893859Sml29623 		NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_intr: not ready"));
1903859Sml29623 		return (DDI_INTR_UNCLAIMED);
1913859Sml29623 	}
1923859Sml29623 	/*
1933859Sml29623 	 * This interrupt handler will have to go through all the logical
1943859Sml29623 	 * devices to find out which logical device interrupts us and then call
1953859Sml29623 	 * its handler to process the events.
1963859Sml29623 	 */
1973859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
1983859Sml29623 	t_ldgp = ldgp;
1993859Sml29623 	t_ldvp = ldgp->ldvp;
2003859Sml29623 
2013859Sml29623 	nldvs = ldgp->nldvs;
2023859Sml29623 
2033859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: #ldvs %d #intrs %d",
2043859Sml29623 			nldvs, ldgvp->ldg_intrs));
2053859Sml29623 
2063859Sml29623 	serviced = DDI_INTR_CLAIMED;
2073859Sml29623 	for (i = 0; i < nintrs; i++, t_ldgp++) {
2083859Sml29623 		NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr(%d): #ldvs %d "
2093859Sml29623 				" #intrs %d", i, nldvs, nintrs));
2103859Sml29623 		/* Get this group's flag bits.  */
2113859Sml29623 		t_ldgp->interrupted = B_FALSE;
2123859Sml29623 		rs = npi_ldsv_ldfs_get(handle, t_ldgp->ldg,
2133859Sml29623 			&vector0, &vector1, &vector2);
2143859Sml29623 		if (rs) {
2153859Sml29623 			continue;
2163859Sml29623 		}
2173859Sml29623 		if (!vector0 && !vector1 && !vector2) {
2183859Sml29623 			NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: "
2193859Sml29623 				"no interrupts on group %d", t_ldgp->ldg));
2203859Sml29623 			continue;
2213859Sml29623 		}
2223859Sml29623 		NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: "
2233859Sml29623 			"vector0 0x%llx vector1 0x%llx vector2 0x%llx",
2243859Sml29623 			vector0, vector1, vector2));
2253859Sml29623 		t_ldgp->interrupted = B_TRUE;
2263859Sml29623 		nldvs = t_ldgp->nldvs;
2273859Sml29623 		for (j = 0; j < nldvs; j++, t_ldvp++) {
2283859Sml29623 			/*
2293859Sml29623 			 * Call device's handler if flag bits are on.
2303859Sml29623 			 */
2313859Sml29623 			ldv = t_ldvp->ldv;
2323859Sml29623 			if (((ldv < NXGE_MAC_LD_START) &&
2333859Sml29623 					(LDV_ON(ldv, vector0) |
2343859Sml29623 					(LDV_ON(ldv, vector1)))) ||
2353859Sml29623 					(ldv >= NXGE_MAC_LD_START &&
2363859Sml29623 					((LDV2_ON_1(ldv, vector2)) ||
2373859Sml29623 					(LDV2_ON_2(ldv, vector2))))) {
2383859Sml29623 				(void) (t_ldvp->ldv_intr_handler)(
2393859Sml29623 					(caddr_t)t_ldvp, arg2);
2403859Sml29623 				NXGE_DEBUG_MSG((nxgep, INT_CTL,
2413859Sml29623 					"==> nxge_intr: "
2423859Sml29623 					"calling device %d #ldvs %d #intrs %d",
2433859Sml29623 					j, nldvs, nintrs));
2443859Sml29623 			}
2453859Sml29623 		}
2463859Sml29623 	}
2473859Sml29623 
2483859Sml29623 	t_ldgp = ldgp;
2493859Sml29623 	for (i = 0; i < nintrs; i++, t_ldgp++) {
2503859Sml29623 		/* rearm group interrupts */
2513859Sml29623 		if (t_ldgp->interrupted) {
2523859Sml29623 			NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: arm "
2533859Sml29623 				"group %d", t_ldgp->ldg));
2543859Sml29623 			(void) npi_intr_ldg_mgmt_set(handle, t_ldgp->ldg,
2553859Sml29623 				t_ldgp->arm, t_ldgp->ldg_timer);
2563859Sml29623 		}
2573859Sml29623 	}
2583859Sml29623 
2593859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr: serviced 0x%x",
2603859Sml29623 		serviced));
2613859Sml29623 	return (serviced);
2623859Sml29623 }
2633859Sml29623 
2643859Sml29623 /* ARGSUSED */
265*5060Syc148097 static nxge_status_t
266*5060Syc148097 nxge_check_xaui_xfp(p_nxge_t nxgep)
267*5060Syc148097 {
268*5060Syc148097 	nxge_status_t	status = NXGE_OK;
269*5060Syc148097 	uint8_t		phy_port_addr;
270*5060Syc148097 	uint16_t	val;
271*5060Syc148097 	uint16_t	val1;
272*5060Syc148097 	uint8_t		portn;
273*5060Syc148097 
274*5060Syc148097 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_check_xaui_xfp"));
275*5060Syc148097 
276*5060Syc148097 	portn = nxgep->mac.portnum;
277*5060Syc148097 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
278*5060Syc148097 
279*5060Syc148097 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
280*5060Syc148097 	    BCM8704_USER_DEV3_ADDR,
281*5060Syc148097 	    BCM8704_USER_ANALOG_STATUS0_REG, &val)) == NXGE_OK) {
282*5060Syc148097 		status = nxge_mdio_read(nxgep, phy_port_addr,
283*5060Syc148097 		    BCM8704_USER_DEV3_ADDR,
284*5060Syc148097 		    BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
285*5060Syc148097 	}
286*5060Syc148097 	if (status != NXGE_OK) {
287*5060Syc148097 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
288*5060Syc148097 		    NXGE_FM_EREPORT_XAUI_ERR);
289*5060Syc148097 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
290*5060Syc148097 		    "XAUI is bad or absent on port<%d>\n", portn));
291*5060Syc148097 	} else if (nxgep->mac.portmode == PORT_10G_FIBER) {
292*5060Syc148097 		/*
293*5060Syc148097 		 * 0x03FC = 0000 0011 1111 1100
294*5060Syc148097 		 * 0x639C = 0110 0011 1001 1100
295*5060Syc148097 		 * bit14 = 1: PDM loss-of-light indicator
296*5060Syc148097 		 * bit13 = 1: PDM Rx loss-of-signal
297*5060Syc148097 		 * bit6  = 0: Light is NOT ok
298*5060Syc148097 		 * bit5  = 0: PMD Rx signal is NOT ok
299*5060Syc148097 		 */
300*5060Syc148097 		if (val != 0x3FC && val == 0x639C) {
301*5060Syc148097 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
302*5060Syc148097 			    NXGE_FM_EREPORT_XFP_ERR);
303*5060Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
304*5060Syc148097 			    "XFP is bad or absent on port<%d>\n", portn));
305*5060Syc148097 			status = NXGE_ERROR;
306*5060Syc148097 		}
307*5060Syc148097 	}
308*5060Syc148097 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_check_xaui_xfp"));
309*5060Syc148097 	return (status);
310*5060Syc148097 }
311*5060Syc148097 
312*5060Syc148097 
313*5060Syc148097 /* ARGSUSED */
3143859Sml29623 uint_t
3153859Sml29623 nxge_syserr_intr(void *arg1, void *arg2)
3163859Sml29623 {
3173859Sml29623 	p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
3183859Sml29623 	p_nxge_t nxgep = (p_nxge_t)arg2;
3193859Sml29623 	p_nxge_ldg_t ldgp = NULL;
3203859Sml29623 	npi_handle_t handle;
3213859Sml29623 	sys_err_stat_t estat;
3223859Sml29623 	uint_t serviced = DDI_INTR_UNCLAIMED;
3233859Sml29623 
3243859Sml29623 	if (arg1 == NULL && arg2 == NULL) {
3253859Sml29623 		return (serviced);
3263859Sml29623 	}
3273859Sml29623 	if (arg2 == NULL || ((ldvp != NULL && (void *) ldvp->nxgep != arg2))) {
3283859Sml29623 		if (ldvp != NULL) {
3293859Sml29623 			nxgep = ldvp->nxgep;
3303859Sml29623 		}
3313859Sml29623 	}
3323859Sml29623 	NXGE_DEBUG_MSG((nxgep, SYSERR_CTL,
3333859Sml29623 		"==> nxge_syserr_intr: arg2 $%p arg1 $%p", nxgep, ldvp));
3343859Sml29623 	if (ldvp != NULL && ldvp->use_timer == B_FALSE) {
3353859Sml29623 		ldgp = ldvp->ldgp;
3363859Sml29623 		if (ldgp == NULL) {
3373859Sml29623 			NXGE_ERROR_MSG((nxgep, SYSERR_CTL,
3383859Sml29623 				"<== nxge_syserrintr(no logical group): "
3393859Sml29623 				"arg2 $%p arg1 $%p", nxgep, ldvp));
3403859Sml29623 			return (DDI_INTR_UNCLAIMED);
3413859Sml29623 		}
3423859Sml29623 		/*
3433859Sml29623 		 * Get the logical device state if the function uses interrupt.
3443859Sml29623 		 */
3453859Sml29623 	}
3463859Sml29623 
3473859Sml29623 	/* This interrupt handler is for system error interrupts.  */
3483859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
3493859Sml29623 	estat.value = 0;
3503859Sml29623 	(void) npi_fzc_sys_err_stat_get(handle, &estat);
3513859Sml29623 	NXGE_DEBUG_MSG((nxgep, SYSERR_CTL,
3523859Sml29623 		"==> nxge_syserr_intr: device error 0x%016llx", estat.value));
3533859Sml29623 
3543859Sml29623 	if (estat.bits.ldw.smx) {
3553859Sml29623 		/* SMX */
3563859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3573859Sml29623 			"==> nxge_syserr_intr: device error - SMX"));
3583859Sml29623 	} else if (estat.bits.ldw.mac) {
3593859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3603859Sml29623 			"==> nxge_syserr_intr: device error - MAC"));
3613859Sml29623 		/*
3623859Sml29623 		 * There is nothing to be done here. All MAC errors go to per
3633859Sml29623 		 * MAC port interrupt. MIF interrupt is the only MAC sub-block
3643859Sml29623 		 * that can generate status here. MIF status reported will be
3653859Sml29623 		 * ignored here. It is checked by per port timer instead.
3663859Sml29623 		 */
3673859Sml29623 	} else if (estat.bits.ldw.ipp) {
3683859Sml29623 		NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
3693859Sml29623 			"==> nxge_syserr_intr: device error - IPP"));
3703859Sml29623 		(void) nxge_ipp_handle_sys_errors(nxgep);
3713859Sml29623 	} else if (estat.bits.ldw.zcp) {
3723859Sml29623 		/* ZCP */
3733859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3743859Sml29623 			"==> nxge_syserr_intr: device error - ZCP"));
3753859Sml29623 		(void) nxge_zcp_handle_sys_errors(nxgep);
3763859Sml29623 	} else if (estat.bits.ldw.tdmc) {
3773859Sml29623 		/* TDMC */
3783859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3793859Sml29623 			"==> nxge_syserr_intr: device error - TDMC"));
3803859Sml29623 		/*
3813859Sml29623 		 * There is no TDMC system errors defined in the PRM. All TDMC
3823859Sml29623 		 * channel specific errors are reported on a per channel basis.
3833859Sml29623 		 */
3843859Sml29623 	} else if (estat.bits.ldw.rdmc) {
3853859Sml29623 		/* RDMC */
3863859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3873859Sml29623 			"==> nxge_syserr_intr: device error - RDMC"));
3883859Sml29623 		(void) nxge_rxdma_handle_sys_errors(nxgep);
3893859Sml29623 	} else if (estat.bits.ldw.txc) {
3903859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3913859Sml29623 			"==> nxge_syserr_intr: device error - TXC"));
3923859Sml29623 		(void) nxge_txc_handle_sys_errors(nxgep);
3933859Sml29623 	} else if ((nxgep->niu_type != N2_NIU) && estat.bits.ldw.peu) {
3943859Sml29623 		/* PCI-E */
3953859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3963859Sml29623 			"==> nxge_syserr_intr: device error - PCI-E"));
3973859Sml29623 	} else if (estat.bits.ldw.meta1) {
3983859Sml29623 		/* META1 */
3993859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4003859Sml29623 			"==> nxge_syserr_intr: device error - META1"));
4013859Sml29623 	} else if (estat.bits.ldw.meta2) {
4023859Sml29623 		/* META2 */
4033859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4043859Sml29623 			"==> nxge_syserr_intr: device error - META2"));
4053859Sml29623 	} else if (estat.bits.ldw.fflp) {
4063859Sml29623 		/* FFLP */
4073859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4083859Sml29623 			"==> nxge_syserr_intr: device error - FFLP"));
4093859Sml29623 		(void) nxge_fflp_handle_sys_errors(nxgep);
4103859Sml29623 	}
411*5060Syc148097 
412*5060Syc148097 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
413*5060Syc148097 	    nxgep->mac.portmode == PORT_10G_COPPER) {
414*5060Syc148097 		if (nxge_check_xaui_xfp(nxgep) != NXGE_OK) {
415*5060Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
416*5060Syc148097 			    "==> nxge_syserr_intr: device error - XAUI"));
417*5060Syc148097 		}
418*5060Syc148097 	}
419*5060Syc148097 
4203859Sml29623 	serviced = DDI_INTR_CLAIMED;
4213859Sml29623 
4223859Sml29623 	if (ldgp != NULL && ldvp != NULL && ldgp->nldvs == 1 &&
4233859Sml29623 		!ldvp->use_timer) {
4243859Sml29623 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
4253859Sml29623 			B_TRUE, ldgp->ldg_timer);
4263859Sml29623 	}
4273859Sml29623 	NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_syserr_intr"));
4283859Sml29623 	return (serviced);
4293859Sml29623 }
4303859Sml29623 
4313859Sml29623 /* ARGSUSED */
4323859Sml29623 void
4333859Sml29623 nxge_intr_hw_enable(p_nxge_t nxgep)
4343859Sml29623 {
4353859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_hw_enable"));
4363859Sml29623 	(void) nxge_intr_mask_mgmt_set(nxgep, B_TRUE);
4373859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_hw_enable"));
4383859Sml29623 }
4393859Sml29623 
4403859Sml29623 /* ARGSUSED */
4413859Sml29623 void
4423859Sml29623 nxge_intr_hw_disable(p_nxge_t nxgep)
4433859Sml29623 {
4443859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_hw_disable"));
4453859Sml29623 	(void) nxge_intr_mask_mgmt_set(nxgep, B_FALSE);
4463859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_hw_disable"));
4473859Sml29623 }
4483859Sml29623 
4493859Sml29623 /* ARGSUSED */
4503859Sml29623 void
4513859Sml29623 nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count)
4523859Sml29623 {
4533859Sml29623 	p_nxge_t nxgep = (p_nxge_t)arg;
4543859Sml29623 	uint8_t channel;
4553859Sml29623 	npi_handle_t handle;
4563859Sml29623 	p_nxge_ldgv_t ldgvp;
4573859Sml29623 	p_nxge_ldv_t ldvp;
4583859Sml29623 	int i;
4593859Sml29623 
4603859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_rx_hw_blank"));
4613859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
4623859Sml29623 
4633859Sml29623 	if ((ldgvp = nxgep->ldgvp) == NULL) {
4643859Sml29623 		NXGE_ERROR_MSG((nxgep, INT_CTL,
4653859Sml29623 			"<== nxge_rx_hw_blank (not enabled)"));
4663859Sml29623 		return;
4673859Sml29623 	}
4683859Sml29623 	ldvp = nxgep->ldgvp->ldvp;
4693859Sml29623 	if (ldvp == NULL) {
4703859Sml29623 		return;
4713859Sml29623 	}
4723859Sml29623 	for (i = 0; i < ldgvp->nldvs; i++, ldvp++) {
4733859Sml29623 		if (ldvp->is_rxdma) {
4743859Sml29623 			channel = ldvp->channel;
4753859Sml29623 			(void) npi_rxdma_cfg_rdc_rcr_threshold(handle,
4763859Sml29623 				channel, count);
4773859Sml29623 			(void) npi_rxdma_cfg_rdc_rcr_timeout(handle,
4783859Sml29623 				channel, ticks);
4793859Sml29623 		}
4803859Sml29623 	}
4813859Sml29623 
4823859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_rx_hw_blank"));
4833859Sml29623 }
4843859Sml29623 
4853859Sml29623 /* ARGSUSED */
4863859Sml29623 void
4873859Sml29623 nxge_hw_stop(p_nxge_t nxgep)
4883859Sml29623 {
4893859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_stop"));
4903859Sml29623 
4913859Sml29623 	(void) nxge_tx_mac_disable(nxgep);
4923859Sml29623 	(void) nxge_rx_mac_disable(nxgep);
4933859Sml29623 	(void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
4943859Sml29623 	(void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
4953859Sml29623 
4963859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_stop"));
4973859Sml29623 }
4983859Sml29623 
4993859Sml29623 /* ARGSUSED */
5003859Sml29623 void
5013859Sml29623 nxge_hw_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
5023859Sml29623 {
5033859Sml29623 	int cmd;
5043859Sml29623 
5053859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_hw_ioctl"));
5063859Sml29623 
5073859Sml29623 	if (nxgep == NULL) {
5083859Sml29623 		miocnak(wq, mp, 0, EINVAL);
5093859Sml29623 		return;
5103859Sml29623 	}
5113859Sml29623 	iocp->ioc_error = 0;
5123859Sml29623 	cmd = iocp->ioc_cmd;
5133859Sml29623 
5143859Sml29623 	switch (cmd) {
5153859Sml29623 	default:
5163859Sml29623 		miocnak(wq, mp, 0, EINVAL);
5173859Sml29623 		return;
5183859Sml29623 
5193859Sml29623 	case NXGE_GET_MII:
5203859Sml29623 		nxge_get_mii(nxgep, mp->b_cont);
5213859Sml29623 		miocack(wq, mp, sizeof (uint16_t), 0);
5223859Sml29623 		break;
5233859Sml29623 
5243859Sml29623 	case NXGE_PUT_MII:
5253859Sml29623 		nxge_put_mii(nxgep, mp->b_cont);
5263859Sml29623 		miocack(wq, mp, 0, 0);
5273859Sml29623 		break;
5283859Sml29623 
5293859Sml29623 	case NXGE_GET64:
5303859Sml29623 		nxge_get64(nxgep, mp->b_cont);
5313859Sml29623 		miocack(wq, mp, sizeof (uint32_t), 0);
5323859Sml29623 		break;
5333859Sml29623 
5343859Sml29623 	case NXGE_PUT64:
5353859Sml29623 		nxge_put64(nxgep, mp->b_cont);
5363859Sml29623 		miocack(wq, mp, 0, 0);
5373859Sml29623 		break;
5383859Sml29623 
5393859Sml29623 	case NXGE_PUT_TCAM:
5403859Sml29623 		nxge_put_tcam(nxgep, mp->b_cont);
5413859Sml29623 		miocack(wq, mp, 0, 0);
5423859Sml29623 		break;
5433859Sml29623 
5443859Sml29623 	case NXGE_GET_TCAM:
5453859Sml29623 		nxge_get_tcam(nxgep, mp->b_cont);
5463859Sml29623 		miocack(wq, mp, 0, 0);
5473859Sml29623 		break;
5483859Sml29623 
5493859Sml29623 	case NXGE_TX_REGS_DUMP:
5503859Sml29623 		nxge_txdma_regs_dump_channels(nxgep);
5513859Sml29623 		miocack(wq, mp, 0, 0);
5523859Sml29623 		break;
5533859Sml29623 	case NXGE_RX_REGS_DUMP:
5543859Sml29623 		nxge_rxdma_regs_dump_channels(nxgep);
5553859Sml29623 		miocack(wq, mp, 0, 0);
5563859Sml29623 		break;
5573859Sml29623 	case NXGE_VIR_INT_REGS_DUMP:
5583859Sml29623 	case NXGE_INT_REGS_DUMP:
5593859Sml29623 		nxge_virint_regs_dump(nxgep);
5603859Sml29623 		miocack(wq, mp, 0, 0);
5613859Sml29623 		break;
5623859Sml29623 	case NXGE_RTRACE:
5633859Sml29623 		nxge_rtrace_ioctl(nxgep, wq, mp, iocp);
5643859Sml29623 		break;
5653859Sml29623 	}
5663859Sml29623 }
5673859Sml29623 
5683859Sml29623 /* ARGSUSED */
5693859Sml29623 void
5703859Sml29623 nxge_loopback_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp,
5713859Sml29623 	struct iocblk *iocp)
5723859Sml29623 {
5733859Sml29623 	p_lb_property_t lb_props;
5743859Sml29623 
5753859Sml29623 	size_t size;
5763859Sml29623 	int i;
5773859Sml29623 
5783859Sml29623 	if (mp->b_cont == NULL) {
5793859Sml29623 		miocnak(wq, mp, 0, EINVAL);
5803859Sml29623 	}
5813859Sml29623 	switch (iocp->ioc_cmd) {
5823859Sml29623 	case LB_GET_MODE:
5833859Sml29623 		NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_GET_LB_MODE command"));
5843859Sml29623 		if (nxgep != NULL) {
5853859Sml29623 			*(lb_info_sz_t *)mp->b_cont->b_rptr =
5863859Sml29623 				nxgep->statsp->port_stats.lb_mode;
5873859Sml29623 			miocack(wq, mp, sizeof (nxge_lb_t), 0);
588*5060Syc148097 		} else {
5893859Sml29623 			miocnak(wq, mp, 0, EINVAL);
590*5060Syc148097 		}
5913859Sml29623 		break;
5923859Sml29623 	case LB_SET_MODE:
5933859Sml29623 		NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_SET_LB_MODE command"));
5943859Sml29623 		if (iocp->ioc_count != sizeof (uint32_t)) {
5953859Sml29623 			miocack(wq, mp, 0, 0);
5963859Sml29623 			break;
5973859Sml29623 		}
5983859Sml29623 		if ((nxgep != NULL) && nxge_set_lb(nxgep, wq, mp->b_cont)) {
5993859Sml29623 			miocack(wq, mp, 0, 0);
6003859Sml29623 		} else {
6013859Sml29623 			miocnak(wq, mp, 0, EPROTO);
6023859Sml29623 		}
6033859Sml29623 		break;
6043859Sml29623 	case LB_GET_INFO_SIZE:
6053859Sml29623 		NXGE_DEBUG_MSG((nxgep, IOC_CTL, "LB_GET_INFO_SIZE command"));
6063859Sml29623 		if (nxgep != NULL) {
6073859Sml29623 			size = sizeof (lb_normal);
6083859Sml29623 			if (nxgep->statsp->mac_stats.cap_10gfdx) {
6093859Sml29623 				size += sizeof (lb_external10g);
6103859Sml29623 				size += sizeof (lb_phy10g);
6113859Sml29623 				size += sizeof (lb_serdes10g);
6123859Sml29623 				size += sizeof (lb_mac10g);
6133859Sml29623 			}
6143859Sml29623 			if (nxgep->statsp->mac_stats.cap_1000fdx) {
6153859Sml29623 				size += sizeof (lb_external1000);
6163859Sml29623 				size += sizeof (lb_mac1000);
6173859Sml29623 				if (nxgep->mac.portmode == PORT_1G_COPPER)
6183859Sml29623 					size += sizeof (lb_phy1000);
6193859Sml29623 			}
6203859Sml29623 			if (nxgep->statsp->mac_stats.cap_100fdx)
6213859Sml29623 				size += sizeof (lb_external100);
6223859Sml29623 			if (nxgep->statsp->mac_stats.cap_10fdx)
6233859Sml29623 				size += sizeof (lb_external10);
6244977Sraghus 			else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
6254977Sraghus 			    (nxgep->mac.portmode == PORT_1G_SERDES))
6263859Sml29623 				size += sizeof (lb_serdes1000);
6274977Sraghus 
6283859Sml29623 			*(lb_info_sz_t *)mp->b_cont->b_rptr = size;
6293859Sml29623 
6303859Sml29623 			NXGE_DEBUG_MSG((nxgep, IOC_CTL,
6313859Sml29623 				"NXGE_GET_LB_INFO command: size %d", size));
6323859Sml29623 			miocack(wq, mp, sizeof (lb_info_sz_t), 0);
6333859Sml29623 		} else
6343859Sml29623 			miocnak(wq, mp, 0, EINVAL);
6353859Sml29623 		break;
6363859Sml29623 
6373859Sml29623 	case LB_GET_INFO:
6383859Sml29623 		NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_GET_LB_INFO command"));
6393859Sml29623 		if (nxgep != NULL) {
6403859Sml29623 			size = sizeof (lb_normal);
6413859Sml29623 			if (nxgep->statsp->mac_stats.cap_10gfdx) {
6423859Sml29623 				size += sizeof (lb_external10g);
6433859Sml29623 				size += sizeof (lb_phy10g);
6443859Sml29623 				size += sizeof (lb_serdes10g);
6453859Sml29623 				size += sizeof (lb_mac10g);
6463859Sml29623 			}
6473859Sml29623 			if (nxgep->statsp->mac_stats.cap_1000fdx) {
6483859Sml29623 				size += sizeof (lb_external1000);
6493859Sml29623 				size += sizeof (lb_mac1000);
6503859Sml29623 				if (nxgep->mac.portmode == PORT_1G_COPPER)
6513859Sml29623 					size += sizeof (lb_phy1000);
6523859Sml29623 			}
6533859Sml29623 			if (nxgep->statsp->mac_stats.cap_100fdx)
6543859Sml29623 				size += sizeof (lb_external100);
6553859Sml29623 			if (nxgep->statsp->mac_stats.cap_10fdx)
6563859Sml29623 				size += sizeof (lb_external10);
6574977Sraghus 			else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
6584977Sraghus 			    (nxgep->mac.portmode == PORT_1G_SERDES))
6593859Sml29623 				size += sizeof (lb_serdes1000);
6603859Sml29623 
6613859Sml29623 			NXGE_DEBUG_MSG((nxgep, IOC_CTL,
6623859Sml29623 				"NXGE_GET_LB_INFO command: size %d", size));
6633859Sml29623 			if (size == iocp->ioc_count) {
6643859Sml29623 				i = 0;
6653859Sml29623 				lb_props = (p_lb_property_t)mp->b_cont->b_rptr;
6663859Sml29623 				lb_props[i++] = lb_normal;
6673859Sml29623 				if (nxgep->statsp->mac_stats.cap_10gfdx) {
6683859Sml29623 					lb_props[i++] = lb_mac10g;
6693859Sml29623 					lb_props[i++] = lb_serdes10g;
6703859Sml29623 					lb_props[i++] = lb_phy10g;
6713859Sml29623 					lb_props[i++] = lb_external10g;
6723859Sml29623 				}
6733859Sml29623 				if (nxgep->statsp->mac_stats.cap_1000fdx)
6743859Sml29623 					lb_props[i++] = lb_external1000;
6753859Sml29623 				if (nxgep->statsp->mac_stats.cap_100fdx)
6763859Sml29623 					lb_props[i++] = lb_external100;
6773859Sml29623 				if (nxgep->statsp->mac_stats.cap_10fdx)
6783859Sml29623 					lb_props[i++] = lb_external10;
6793859Sml29623 				if (nxgep->statsp->mac_stats.cap_1000fdx)
6803859Sml29623 					lb_props[i++] = lb_mac1000;
6813859Sml29623 				if (nxgep->mac.portmode == PORT_1G_COPPER) {
6823859Sml29623 					if (nxgep->statsp->mac_stats.
6833859Sml29623 						cap_1000fdx)
6843859Sml29623 						lb_props[i++] = lb_phy1000;
6854977Sraghus 				} else if ((nxgep->mac.portmode ==
6864977Sraghus 				    PORT_1G_FIBER) ||
6874977Sraghus 				    (nxgep->mac.portmode == PORT_1G_SERDES)) {
6883859Sml29623 					lb_props[i++] = lb_serdes1000;
6894977Sraghus 				}
6903859Sml29623 				miocack(wq, mp, size, 0);
6913859Sml29623 			} else
6923859Sml29623 				miocnak(wq, mp, 0, EINVAL);
6933859Sml29623 		} else {
6943859Sml29623 			miocnak(wq, mp, 0, EINVAL);
6953859Sml29623 			cmn_err(CE_NOTE, "!nxge_hw_ioctl: invalid command 0x%x",
6963859Sml29623 				iocp->ioc_cmd);
6973859Sml29623 		}
6983859Sml29623 		break;
6993859Sml29623 	}
7003859Sml29623 }
7013859Sml29623 
7023859Sml29623 /*
7033859Sml29623  * DMA channel interfaces to access various channel specific
7043859Sml29623  * hardware functions.
7053859Sml29623  */
7063859Sml29623 /* ARGSUSED */
7073859Sml29623 void
7083859Sml29623 nxge_rxdma_channel_put64(nxge_os_acc_handle_t handle, void *reg_addrp,
7093859Sml29623 	uint32_t reg_base, uint16_t channel, uint64_t reg_data)
7103859Sml29623 {
7113859Sml29623 	uint64_t reg_offset;
7123859Sml29623 
7133859Sml29623 	NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_put64"));
7143859Sml29623 
7153859Sml29623 	/*
7163859Sml29623 	 * Channel is assumed to be from 0 to the maximum DMA channel #. If we
7173859Sml29623 	 * use the virtual DMA CSR address space from the config space (in PCI
7183859Sml29623 	 * case), then the following code need to be use different offset
7193859Sml29623 	 * computation macro.
7203859Sml29623 	 */
7213859Sml29623 	reg_offset = reg_base + DMC_OFFSET(channel);
7223859Sml29623 	NXGE_PIO_WRITE64(handle, reg_addrp, reg_offset, reg_data);
7233859Sml29623 
7243859Sml29623 	NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_put64"));
7253859Sml29623 }
7263859Sml29623 
7273859Sml29623 /* ARGSUSED */
7283859Sml29623 uint64_t
7293859Sml29623 nxge_rxdma_channel_get64(nxge_os_acc_handle_t handle, void *reg_addrp,
7303859Sml29623 	uint32_t reg_base, uint16_t channel)
7313859Sml29623 {
7323859Sml29623 	uint64_t reg_offset;
7333859Sml29623 
7343859Sml29623 	NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_get64"));
7353859Sml29623 
7363859Sml29623 	/*
7373859Sml29623 	 * Channel is assumed to be from 0 to the maximum DMA channel #. If we
7383859Sml29623 	 * use the virtual DMA CSR address space from the config space (in PCI
7393859Sml29623 	 * case), then the following code need to be use different offset
7403859Sml29623 	 * computation macro.
7413859Sml29623 	 */
7423859Sml29623 	reg_offset = reg_base + DMC_OFFSET(channel);
7433859Sml29623 
7443859Sml29623 	NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_get64"));
7453859Sml29623 
7463859Sml29623 	return (NXGE_PIO_READ64(handle, reg_addrp, reg_offset));
7473859Sml29623 }
7483859Sml29623 
7493859Sml29623 /* ARGSUSED */
7503859Sml29623 void
7513859Sml29623 nxge_get32(p_nxge_t nxgep, p_mblk_t mp)
7523859Sml29623 {
7533859Sml29623 	nxge_os_acc_handle_t nxge_regh;
7543859Sml29623 
7553859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_get32"));
7563859Sml29623 	nxge_regh = nxgep->dev_regs->nxge_regh;
7573859Sml29623 
7583859Sml29623 	*(uint32_t *)mp->b_rptr = NXGE_PIO_READ32(nxge_regh,
7593859Sml29623 		nxgep->dev_regs->nxge_regp, *(uint32_t *)mp->b_rptr);
7603859Sml29623 
7613859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "value = 0x%08X",
7623859Sml29623 		*(uint32_t *)mp->b_rptr));
7633859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_get32"));
7643859Sml29623 }
7653859Sml29623 
7663859Sml29623 /* ARGSUSED */
7673859Sml29623 void
7683859Sml29623 nxge_put32(p_nxge_t nxgep, p_mblk_t mp)
7693859Sml29623 {
7703859Sml29623 	nxge_os_acc_handle_t nxge_regh;
7713859Sml29623 	uint32_t *buf;
7723859Sml29623 	uint8_t *reg;
7733859Sml29623 
7743859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_put32"));
7753859Sml29623 	nxge_regh = nxgep->dev_regs->nxge_regh;
7763859Sml29623 
7773859Sml29623 	buf = (uint32_t *)mp->b_rptr;
7783859Sml29623 	reg = (uint8_t *)(nxgep->dev_regs->nxge_regp) + buf[0];
7793859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL,
7803859Sml29623 		"reg = 0x%016llX index = 0x%08X value = 0x%08X",
7813859Sml29623 		reg, buf[0], buf[1]));
7823859Sml29623 	NXGE_PIO_WRITE32(nxge_regh, (uint32_t *)reg, 0, buf[1]);
7833859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_put32"));
7843859Sml29623 }
7853859Sml29623 
7863859Sml29623 /*ARGSUSED*/
7873859Sml29623 boolean_t
7883859Sml29623 nxge_set_lb(p_nxge_t nxgep, queue_t *wq, p_mblk_t mp)
7893859Sml29623 {
7903859Sml29623 	boolean_t status = B_TRUE;
7913859Sml29623 	uint32_t lb_mode;
7923859Sml29623 	lb_property_t *lb_info;
7933859Sml29623 
7943859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_set_lb"));
7953859Sml29623 	lb_mode = nxgep->statsp->port_stats.lb_mode;
7963859Sml29623 	if (lb_mode == *(uint32_t *)mp->b_rptr) {
7973859Sml29623 		cmn_err(CE_NOTE,
7983859Sml29623 			"!nxge%d: Loopback mode already set (lb_mode %d).\n",
7993859Sml29623 			nxgep->instance, lb_mode);
8003859Sml29623 		status = B_FALSE;
8013859Sml29623 		goto nxge_set_lb_exit;
8023859Sml29623 	}
8033859Sml29623 	lb_mode = *(uint32_t *)mp->b_rptr;
8043859Sml29623 	lb_info = NULL;
8053859Sml29623 	if (lb_mode == lb_normal.value)
8063859Sml29623 		lb_info = &lb_normal;
8073859Sml29623 	else if ((lb_mode == lb_external10g.value) &&
8083859Sml29623 		(nxgep->statsp->mac_stats.cap_10gfdx))
8093859Sml29623 		lb_info = &lb_external10g;
8103859Sml29623 	else if ((lb_mode == lb_external1000.value) &&
8113859Sml29623 		(nxgep->statsp->mac_stats.cap_1000fdx))
8123859Sml29623 		lb_info = &lb_external1000;
8133859Sml29623 	else if ((lb_mode == lb_external100.value) &&
8143859Sml29623 		(nxgep->statsp->mac_stats.cap_100fdx))
8153859Sml29623 		lb_info = &lb_external100;
8163859Sml29623 	else if ((lb_mode == lb_external10.value) &&
8173859Sml29623 		(nxgep->statsp->mac_stats.cap_10fdx))
8183859Sml29623 		lb_info = &lb_external10;
8193859Sml29623 	else if ((lb_mode == lb_phy10g.value) &&
8203859Sml29623 			((nxgep->mac.portmode == PORT_10G_COPPER) ||
8213859Sml29623 			(nxgep->mac.portmode == PORT_10G_FIBER)))
8223859Sml29623 		lb_info = &lb_phy10g;
8233859Sml29623 	else if ((lb_mode == lb_phy1000.value) &&
8243859Sml29623 		(nxgep->mac.portmode == PORT_1G_COPPER))
8253859Sml29623 		lb_info = &lb_phy1000;
8263859Sml29623 	else if ((lb_mode == lb_phy.value) &&
8273859Sml29623 		(nxgep->mac.portmode == PORT_1G_COPPER))
8283859Sml29623 		lb_info = &lb_phy;
8293859Sml29623 	else if ((lb_mode == lb_serdes10g.value) &&
8304977Sraghus 	    ((nxgep->mac.portmode == PORT_10G_FIBER) ||
8314977Sraghus 	    (nxgep->mac.portmode == PORT_10G_COPPER) ||
8324977Sraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)))
8333859Sml29623 		lb_info = &lb_serdes10g;
8343859Sml29623 	else if ((lb_mode == lb_serdes1000.value) &&
8354977Sraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER ||
8364977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)))
8373859Sml29623 		lb_info = &lb_serdes1000;
8383859Sml29623 	else if (lb_mode == lb_mac10g.value)
8393859Sml29623 		lb_info = &lb_mac10g;
8403859Sml29623 	else if (lb_mode == lb_mac1000.value)
8413859Sml29623 		lb_info = &lb_mac1000;
8423859Sml29623 	else if (lb_mode == lb_mac.value)
8433859Sml29623 		lb_info = &lb_mac;
8443859Sml29623 	else {
8453859Sml29623 		cmn_err(CE_NOTE,
8463859Sml29623 			"!nxge%d: Loopback mode not supported(mode %d).\n",
8473859Sml29623 			nxgep->instance, lb_mode);
8483859Sml29623 		status = B_FALSE;
8493859Sml29623 		goto nxge_set_lb_exit;
8503859Sml29623 	}
8513859Sml29623 
8523859Sml29623 	if (lb_mode == nxge_lb_normal) {
8533859Sml29623 		if (nxge_lb_dbg) {
8543859Sml29623 			cmn_err(CE_NOTE,
8553859Sml29623 				"!nxge%d: Returning to normal operation",
8563859Sml29623 				nxgep->instance);
8573859Sml29623 		}
8583859Sml29623 		nxge_set_lb_normal(nxgep);
8593859Sml29623 		goto nxge_set_lb_exit;
8603859Sml29623 	}
8613859Sml29623 	nxgep->statsp->port_stats.lb_mode = lb_mode;
8623859Sml29623 
8633859Sml29623 	if (nxge_lb_dbg)
8643859Sml29623 		cmn_err(CE_NOTE,
8653859Sml29623 			"!nxge%d: Adapter now in %s loopback mode",
8663859Sml29623 			nxgep->instance, lb_info->key);
8673859Sml29623 	nxgep->param_arr[param_autoneg].value = 0;
8683859Sml29623 	nxgep->param_arr[param_anar_10gfdx].value =
8693859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10g) ||
8703859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
8713859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) ||
8723859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g);
8733859Sml29623 	nxgep->param_arr[param_anar_10ghdx].value = 0;
8743859Sml29623 	nxgep->param_arr[param_anar_1000fdx].value =
8753859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
8763859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_mac1000) ||
8773859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
8783859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000);
8793859Sml29623 	nxgep->param_arr[param_anar_1000hdx].value = 0;
8803859Sml29623 	nxgep->param_arr[param_anar_100fdx].value =
8813859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_phy) ||
8823859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_mac) ||
8833859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_ext100);
8843859Sml29623 	nxgep->param_arr[param_anar_100hdx].value = 0;
8853859Sml29623 	nxgep->param_arr[param_anar_10fdx].value =
8863859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_mac) ||
8873859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10);
8883859Sml29623 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) {
8893859Sml29623 		nxgep->param_arr[param_master_cfg_enable].value = 1;
8903859Sml29623 		nxgep->param_arr[param_master_cfg_value].value = 1;
8913859Sml29623 	}
8923859Sml29623 	if ((nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10g) ||
8933859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
8943859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_ext100) ||
8953859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10) ||
8963859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) ||
8973859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
8983859Sml29623 		(nxgep->statsp->port_stats.lb_mode == nxge_lb_phy)) {
8993859Sml29623 
9003859Sml29623 		(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
9014977Sraghus 		(void) nxge_xcvr_find(nxgep);
9023859Sml29623 		(void) nxge_link_init(nxgep);
9033859Sml29623 		(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
9043859Sml29623 	}
9053859Sml29623 	if (lb_info->lb_type == internal) {
9063859Sml29623 		if ((nxgep->statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
9073859Sml29623 				(nxgep->statsp->port_stats.lb_mode ==
9083859Sml29623 				nxge_lb_phy10g) ||
9093859Sml29623 				(nxgep->statsp->port_stats.lb_mode ==
9103859Sml29623 				nxge_lb_serdes10g)) {
9113859Sml29623 			nxgep->statsp->mac_stats.link_speed = 10000;
9123859Sml29623 		} else if ((nxgep->statsp->port_stats.lb_mode
9133859Sml29623 				== nxge_lb_mac1000) ||
9143859Sml29623 				(nxgep->statsp->port_stats.lb_mode ==
9153859Sml29623 				nxge_lb_phy1000) ||
9163859Sml29623 				(nxgep->statsp->port_stats.lb_mode ==
9173859Sml29623 				nxge_lb_serdes1000)) {
9183859Sml29623 			nxgep->statsp->mac_stats.link_speed = 1000;
9193859Sml29623 		} else {
9203859Sml29623 			nxgep->statsp->mac_stats.link_speed = 100;
9213859Sml29623 		}
9223859Sml29623 		nxgep->statsp->mac_stats.link_duplex = 2;
9233859Sml29623 		nxgep->statsp->mac_stats.link_up = 1;
9243859Sml29623 	}
9253859Sml29623 	nxge_global_reset(nxgep);
9263859Sml29623 
9273859Sml29623 nxge_set_lb_exit:
9283859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
9293859Sml29623 		"<== nxge_set_lb status = 0x%08x", status));
9303859Sml29623 	return (status);
9313859Sml29623 }
9323859Sml29623 
9333859Sml29623 /* ARGSUSED */
9343859Sml29623 void
9353859Sml29623 nxge_set_lb_normal(p_nxge_t nxgep)
9363859Sml29623 {
9373859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_lb_normal"));
9383859Sml29623 	nxgep->statsp->port_stats.lb_mode = nxge_lb_normal;
9393859Sml29623 	nxgep->param_arr[param_autoneg].value =
9403859Sml29623 		nxgep->param_arr[param_autoneg].old_value;
9413859Sml29623 	nxgep->param_arr[param_anar_1000fdx].value =
9423859Sml29623 		nxgep->param_arr[param_anar_1000fdx].old_value;
9433859Sml29623 	nxgep->param_arr[param_anar_1000hdx].value =
9443859Sml29623 		nxgep->param_arr[param_anar_1000hdx].old_value;
9453859Sml29623 	nxgep->param_arr[param_anar_100fdx].value =
9463859Sml29623 		nxgep->param_arr[param_anar_100fdx].old_value;
9473859Sml29623 	nxgep->param_arr[param_anar_100hdx].value =
9483859Sml29623 		nxgep->param_arr[param_anar_100hdx].old_value;
9493859Sml29623 	nxgep->param_arr[param_anar_10fdx].value =
9503859Sml29623 		nxgep->param_arr[param_anar_10fdx].old_value;
9513859Sml29623 	nxgep->param_arr[param_master_cfg_enable].value =
9523859Sml29623 		nxgep->param_arr[param_master_cfg_enable].old_value;
9533859Sml29623 	nxgep->param_arr[param_master_cfg_value].value =
9543859Sml29623 		nxgep->param_arr[param_master_cfg_value].old_value;
9553859Sml29623 
9563859Sml29623 	nxge_global_reset(nxgep);
9573859Sml29623 
9583859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
9594977Sraghus 	(void) nxge_xcvr_find(nxgep);
9603859Sml29623 	(void) nxge_link_init(nxgep);
9613859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
9623859Sml29623 
9633859Sml29623 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_lb_normal"));
9643859Sml29623 }
9653859Sml29623 
9663859Sml29623 /* ARGSUSED */
9673859Sml29623 void
9683859Sml29623 nxge_get_mii(p_nxge_t nxgep, p_mblk_t mp)
9693859Sml29623 {
9703859Sml29623 	uint16_t reg;
9713859Sml29623 
9723859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_get_mii"));
9733859Sml29623 
9743859Sml29623 	reg = *(uint16_t *)mp->b_rptr;
9753859Sml29623 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, reg,
9763859Sml29623 		(uint16_t *)mp->b_rptr);
9773859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "reg = 0x%08X value = 0x%04X",
9783859Sml29623 		reg, *(uint16_t *)mp->b_rptr));
9793859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_get_mii"));
9803859Sml29623 }
9813859Sml29623 
9823859Sml29623 /* ARGSUSED */
9833859Sml29623 void
9843859Sml29623 nxge_put_mii(p_nxge_t nxgep, p_mblk_t mp)
9853859Sml29623 {
9863859Sml29623 	uint16_t *buf;
9873859Sml29623 	uint8_t reg;
9883859Sml29623 
9893859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_put_mii"));
9903859Sml29623 	buf = (uint16_t *)mp->b_rptr;
9913859Sml29623 	reg = (uint8_t)buf[0];
9923859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL,
9933859Sml29623 		"reg = 0x%08X index = 0x%08X value = 0x%08X",
9943859Sml29623 		reg, buf[0], buf[1]));
9953859Sml29623 	(void) nxge_mii_write(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
9963859Sml29623 		reg, buf[1]);
9973859Sml29623 	NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_put_mii"));
9983859Sml29623 }
9993859Sml29623 
10003859Sml29623 /* ARGSUSED */
10013859Sml29623 void
10023859Sml29623 nxge_check_hw_state(p_nxge_t nxgep)
10033859Sml29623 {
10043859Sml29623 	p_nxge_ldgv_t ldgvp;
10053859Sml29623 	p_nxge_ldv_t t_ldvp;
10063859Sml29623 
10073859Sml29623 	NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "==> nxge_check_hw_state"));
10083859Sml29623 
10093859Sml29623 	MUTEX_ENTER(nxgep->genlock);
10103859Sml29623 	nxgep->nxge_timerid = 0;
10113859Sml29623 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
10123859Sml29623 		goto nxge_check_hw_state_exit;
10133859Sml29623 	}
10143859Sml29623 	nxge_check_tx_hang(nxgep);
10153859Sml29623 
10163859Sml29623 	ldgvp = nxgep->ldgvp;
10173859Sml29623 	if (ldgvp == NULL || (ldgvp->ldvp_syserr == NULL)) {
10183859Sml29623 		NXGE_ERROR_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state: "
10193859Sml29623 				"NULL ldgvp (interrupt not ready)."));
10203859Sml29623 		goto nxge_check_hw_state_exit;
10213859Sml29623 	}
10223859Sml29623 	t_ldvp = ldgvp->ldvp_syserr;
10233859Sml29623 	if (!t_ldvp->use_timer) {
10243859Sml29623 		NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state: "
10253859Sml29623 				"ldgvp $%p t_ldvp $%p use_timer flag %d",
10263859Sml29623 				ldgvp, t_ldvp, t_ldvp->use_timer));
10273859Sml29623 		goto nxge_check_hw_state_exit;
10283859Sml29623 	}
10293859Sml29623 	if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) {
10303859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
10313859Sml29623 			"port%d Bad register acc handle", nxgep->mac.portnum));
10323859Sml29623 	}
10333859Sml29623 	(void) nxge_syserr_intr((void *) t_ldvp, (void *) nxgep);
10343859Sml29623 
10353859Sml29623 	nxgep->nxge_timerid = nxge_start_timer(nxgep, nxge_check_hw_state,
10363859Sml29623 		NXGE_CHECK_TIMER);
10373859Sml29623 
10383859Sml29623 nxge_check_hw_state_exit:
10393859Sml29623 	MUTEX_EXIT(nxgep->genlock);
10403859Sml29623 	NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state"));
10413859Sml29623 }
10423859Sml29623 
10433859Sml29623 /*ARGSUSED*/
10443859Sml29623 static void
10453859Sml29623 nxge_rtrace_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp,
10463859Sml29623 	struct iocblk *iocp)
10473859Sml29623 {
10483859Sml29623 	ssize_t size;
10493859Sml29623 	rtrace_t *rtp;
10503859Sml29623 	mblk_t *nmp;
10513859Sml29623 	uint32_t i, j;
10523859Sml29623 	uint32_t start_blk;
10533859Sml29623 	uint32_t base_entry;
10543859Sml29623 	uint32_t num_entries;
10553859Sml29623 
10563859Sml29623 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_rtrace_ioctl"));
10573859Sml29623 
10583859Sml29623 	size = 1024;
10593859Sml29623 	if (mp->b_cont == NULL || MBLKL(mp->b_cont) < size) {
10603859Sml29623 		NXGE_DEBUG_MSG((nxgep, STR_CTL,
10613859Sml29623 				"malformed M_IOCTL MBLKL = %d size = %d",
10623859Sml29623 				MBLKL(mp->b_cont), size));
10633859Sml29623 		miocnak(wq, mp, 0, EINVAL);
10643859Sml29623 		return;
10653859Sml29623 	}
10663859Sml29623 	nmp = mp->b_cont;
10673859Sml29623 	rtp = (rtrace_t *)nmp->b_rptr;
10683859Sml29623 	start_blk = rtp->next_idx;
10693859Sml29623 	num_entries = rtp->last_idx;
10703859Sml29623 	base_entry = start_blk * MAX_RTRACE_IOC_ENTRIES;
10713859Sml29623 
10723859Sml29623 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "start_blk = %d\n", start_blk));
10733859Sml29623 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "num_entries = %d\n", num_entries));
10743859Sml29623 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "base_entry = %d\n", base_entry));
10753859Sml29623 
10763859Sml29623 	rtp->next_idx = npi_rtracebuf.next_idx;
10773859Sml29623 	rtp->last_idx = npi_rtracebuf.last_idx;
10783859Sml29623 	rtp->wrapped = npi_rtracebuf.wrapped;
10793859Sml29623 	for (i = 0, j = base_entry; i < num_entries; i++, j++) {
10803859Sml29623 		rtp->buf[i].ctl_addr = npi_rtracebuf.buf[j].ctl_addr;
10813859Sml29623 		rtp->buf[i].val_l32 = npi_rtracebuf.buf[j].val_l32;
10823859Sml29623 		rtp->buf[i].val_h32 = npi_rtracebuf.buf[j].val_h32;
10833859Sml29623 	}
10843859Sml29623 
10853859Sml29623 	nmp->b_wptr = nmp->b_rptr + size;
10863859Sml29623 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_rtrace_ioctl"));
10873859Sml29623 	miocack(wq, mp, (int)size, 0);
10883859Sml29623 }
1089