xref: /onnv-gate/usr/src/uts/common/io/ntxn/unm_nic_ctx.c (revision 8687:5dca9cd6354a)
17956Sxiuyan.wang@Sun.COM /*
27956Sxiuyan.wang@Sun.COM  * CDDL HEADER START
37956Sxiuyan.wang@Sun.COM  *
47956Sxiuyan.wang@Sun.COM  * The contents of this file are subject to the terms of the
57956Sxiuyan.wang@Sun.COM  * Common Development and Distribution License (the "License").
67956Sxiuyan.wang@Sun.COM  * You may not use this file except in compliance with the License.
77956Sxiuyan.wang@Sun.COM  *
87956Sxiuyan.wang@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97956Sxiuyan.wang@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107956Sxiuyan.wang@Sun.COM  * See the License for the specific language governing permissions
117956Sxiuyan.wang@Sun.COM  * and limitations under the License.
127956Sxiuyan.wang@Sun.COM  *
137956Sxiuyan.wang@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147956Sxiuyan.wang@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157956Sxiuyan.wang@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167956Sxiuyan.wang@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177956Sxiuyan.wang@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187956Sxiuyan.wang@Sun.COM  *
197956Sxiuyan.wang@Sun.COM  * CDDL HEADER END
207956Sxiuyan.wang@Sun.COM  */
21*8687SJing.Xiong@Sun.COM 
227956Sxiuyan.wang@Sun.COM /*
237956Sxiuyan.wang@Sun.COM  * Copyright 2008 NetXen, Inc.  All rights reserved.
247956Sxiuyan.wang@Sun.COM  * Use is subject to license terms.
257956Sxiuyan.wang@Sun.COM  */
26*8687SJing.Xiong@Sun.COM 
277956Sxiuyan.wang@Sun.COM #include <sys/types.h>
287956Sxiuyan.wang@Sun.COM #include <sys/conf.h>
297956Sxiuyan.wang@Sun.COM #include <sys/debug.h>
307956Sxiuyan.wang@Sun.COM #include <sys/stropts.h>
317956Sxiuyan.wang@Sun.COM #include <sys/stream.h>
327956Sxiuyan.wang@Sun.COM #include <sys/strlog.h>
337956Sxiuyan.wang@Sun.COM #include <sys/kmem.h>
347956Sxiuyan.wang@Sun.COM #include <sys/stat.h>
357956Sxiuyan.wang@Sun.COM #include <sys/kstat.h>
367956Sxiuyan.wang@Sun.COM #include <sys/vtrace.h>
377956Sxiuyan.wang@Sun.COM #include <sys/dlpi.h>
387956Sxiuyan.wang@Sun.COM #include <sys/strsun.h>
397956Sxiuyan.wang@Sun.COM #include <sys/ethernet.h>
407956Sxiuyan.wang@Sun.COM #include <sys/modctl.h>
417956Sxiuyan.wang@Sun.COM #include <sys/errno.h>
427956Sxiuyan.wang@Sun.COM #include <sys/dditypes.h>
437956Sxiuyan.wang@Sun.COM #include <sys/ddi.h>
447956Sxiuyan.wang@Sun.COM #include <sys/sunddi.h>
457956Sxiuyan.wang@Sun.COM #include <sys/sysmacros.h>
467956Sxiuyan.wang@Sun.COM #include <sys/pci.h>
477956Sxiuyan.wang@Sun.COM 
487956Sxiuyan.wang@Sun.COM #include "unm_nic_hw.h"
497956Sxiuyan.wang@Sun.COM #include "unm_nic.h"
507956Sxiuyan.wang@Sun.COM #include "nic_phan_reg.h"
517956Sxiuyan.wang@Sun.COM #include "nic_cmn.h"
527956Sxiuyan.wang@Sun.COM 
537956Sxiuyan.wang@Sun.COM typedef unsigned int nx_rcode_t;
547956Sxiuyan.wang@Sun.COM 
557956Sxiuyan.wang@Sun.COM #include "nx_errorcode.h"
567956Sxiuyan.wang@Sun.COM #include "nxhal_nic_interface.h"
577956Sxiuyan.wang@Sun.COM 
587956Sxiuyan.wang@Sun.COM #define	NXHAL_VERSION	1
597956Sxiuyan.wang@Sun.COM 
607956Sxiuyan.wang@Sun.COM #define	NX_OS_CRB_RETRY_COUNT	4000
617956Sxiuyan.wang@Sun.COM 
627956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CLEAR		0x00000000
637956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_BIT		0x80000000
647956Sxiuyan.wang@Sun.COM 
657956Sxiuyan.wang@Sun.COM /*
667956Sxiuyan.wang@Sun.COM  * All responses must have the NX_CDRP_CMD_BIT cleared
677956Sxiuyan.wang@Sun.COM  * in the crb NX_CDRP_CRB_OFFSET.
687956Sxiuyan.wang@Sun.COM  */
697956Sxiuyan.wang@Sun.COM #define	NX_CDRP_FORM_RSP(rsp)	(rsp)
707956Sxiuyan.wang@Sun.COM #define	NX_CDRP_IS_RSP(rsp)	(((rsp) & NX_CDRP_CMD_BIT) == 0)
717956Sxiuyan.wang@Sun.COM 
727956Sxiuyan.wang@Sun.COM #define	NX_CDRP_RSP_OK		0x00000001
737956Sxiuyan.wang@Sun.COM #define	NX_CDRP_RSP_FAIL	0x00000002
747956Sxiuyan.wang@Sun.COM #define	NX_CDRP_RSP_TIMEOUT	0x00000003
757956Sxiuyan.wang@Sun.COM 
767956Sxiuyan.wang@Sun.COM /*
777956Sxiuyan.wang@Sun.COM  * All commands must have the NX_CDRP_CMD_BIT set in
787956Sxiuyan.wang@Sun.COM  * the crb NX_CDRP_CRB_OFFSET.
797956Sxiuyan.wang@Sun.COM  */
807956Sxiuyan.wang@Sun.COM #define	NX_CDRP_FORM_CMD(cmd)	(NX_CDRP_CMD_BIT | (cmd))
817956Sxiuyan.wang@Sun.COM #define	NX_CDRP_IS_CMD(cmd)	(((cmd) & NX_CDRP_CMD_BIT) != 0)
827956Sxiuyan.wang@Sun.COM 
837956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_SUBMIT_CAPABILITIES		0x00000001
847956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_READ_MAX_RDS_PER_CTX    0x00000002
857956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_READ_MAX_SDS_PER_CTX    0x00000003
867956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_READ_MAX_RULES_PER_CTX  0x00000004
877956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_READ_MAX_RX_CTX			0x00000005
887956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_READ_MAX_TX_CTX			0x00000006
897956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_CREATE_RX_CTX			0x00000007
907956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_DESTROY_RX_CTX			0x00000008
917956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_CREATE_TX_CTX			0x00000009
927956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_DESTROY_TX_CTX			0x0000000a
937956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_SETUP_STATISTICS		0x0000000e
947956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_GET_STATISTICS			0x0000000f
957956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_DELETE_STATISTICS		0x00000010
967956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_SET_MTU					0x00000012
977956Sxiuyan.wang@Sun.COM #define	NX_CDRP_CMD_MAX						0x00000013
987956Sxiuyan.wang@Sun.COM 
997956Sxiuyan.wang@Sun.COM #define	NX_DESTROY_CTX_RESET		0
1007956Sxiuyan.wang@Sun.COM #define	NX_DESTROY_CTX_D3_RESET		1
1017956Sxiuyan.wang@Sun.COM #define	NX_DESTROY_CTX_MAX		2
1027956Sxiuyan.wang@Sun.COM 
1037956Sxiuyan.wang@Sun.COM /*
1047956Sxiuyan.wang@Sun.COM  * Context state
1057956Sxiuyan.wang@Sun.COM  */
1067956Sxiuyan.wang@Sun.COM #define	NX_HOST_CTX_STATE_FREED		0
1077956Sxiuyan.wang@Sun.COM #define	NX_HOST_CTX_STATE_ALLOCATED	1
1087956Sxiuyan.wang@Sun.COM #define	NX_HOST_CTX_STATE_ACTIVE	2
1097956Sxiuyan.wang@Sun.COM #define	NX_HOST_CTX_STATE_DISABLED	3
1107956Sxiuyan.wang@Sun.COM #define	NX_HOST_CTX_STATE_QUIESCED	4
1117956Sxiuyan.wang@Sun.COM #define	NX_HOST_CTX_STATE_MAX		5
1127956Sxiuyan.wang@Sun.COM 
1137956Sxiuyan.wang@Sun.COM static int
netxen_api_lock(struct unm_adapter_s * adapter)1147956Sxiuyan.wang@Sun.COM netxen_api_lock(struct unm_adapter_s *adapter)
1157956Sxiuyan.wang@Sun.COM {
1167956Sxiuyan.wang@Sun.COM 	u32 done = 0, timeout = 0;
1177956Sxiuyan.wang@Sun.COM 
1187956Sxiuyan.wang@Sun.COM 	for (;;) {
1197956Sxiuyan.wang@Sun.COM 		/* Acquire PCIE HW semaphore5 */
1207956Sxiuyan.wang@Sun.COM 		unm_nic_read_w0(adapter,
1217956Sxiuyan.wang@Sun.COM 		    UNM_PCIE_REG(PCIE_SEM5_LOCK), &done);
1227956Sxiuyan.wang@Sun.COM 
1237956Sxiuyan.wang@Sun.COM 		if (done == 1)
1247956Sxiuyan.wang@Sun.COM 			break;
1257956Sxiuyan.wang@Sun.COM 
1267956Sxiuyan.wang@Sun.COM 		if (++timeout >= NX_OS_CRB_RETRY_COUNT) {
1277956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "%s: lock timeout.\n", __func__);
1287956Sxiuyan.wang@Sun.COM 			return (-1);
1297956Sxiuyan.wang@Sun.COM 		}
1307956Sxiuyan.wang@Sun.COM 
1317956Sxiuyan.wang@Sun.COM 		drv_usecwait(1000);
1327956Sxiuyan.wang@Sun.COM 	}
1337956Sxiuyan.wang@Sun.COM 
1347956Sxiuyan.wang@Sun.COM #if 0
1357956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER);
1367956Sxiuyan.wang@Sun.COM #endif
1377956Sxiuyan.wang@Sun.COM 	return (0);
1387956Sxiuyan.wang@Sun.COM }
1397956Sxiuyan.wang@Sun.COM 
1407956Sxiuyan.wang@Sun.COM static void
netxen_api_unlock(struct unm_adapter_s * adapter)1417956Sxiuyan.wang@Sun.COM netxen_api_unlock(struct unm_adapter_s *adapter)
1427956Sxiuyan.wang@Sun.COM {
1437956Sxiuyan.wang@Sun.COM 	u32 val;
1447956Sxiuyan.wang@Sun.COM 
1457956Sxiuyan.wang@Sun.COM 	/* Release PCIE HW semaphore5 */
1467956Sxiuyan.wang@Sun.COM 	unm_nic_read_w0(adapter,
1477956Sxiuyan.wang@Sun.COM 	    UNM_PCIE_REG(PCIE_SEM5_UNLOCK), &val);
1487956Sxiuyan.wang@Sun.COM }
1497956Sxiuyan.wang@Sun.COM 
1507956Sxiuyan.wang@Sun.COM static u32
netxen_poll_rsp(struct unm_adapter_s * adapter)1517956Sxiuyan.wang@Sun.COM netxen_poll_rsp(struct unm_adapter_s *adapter)
1527956Sxiuyan.wang@Sun.COM {
1537956Sxiuyan.wang@Sun.COM 	u32 raw_rsp, rsp = NX_CDRP_RSP_OK;
1547956Sxiuyan.wang@Sun.COM 	int	timeout = 0;
1557956Sxiuyan.wang@Sun.COM 
1567956Sxiuyan.wang@Sun.COM 	do {
1577956Sxiuyan.wang@Sun.COM 		/* give atleast 1ms for firmware to respond */
1587956Sxiuyan.wang@Sun.COM 		drv_usecwait(1000);
1597956Sxiuyan.wang@Sun.COM 
1607956Sxiuyan.wang@Sun.COM 		if (++timeout > NX_OS_CRB_RETRY_COUNT)
1617956Sxiuyan.wang@Sun.COM 			return (NX_CDRP_RSP_TIMEOUT);
1627956Sxiuyan.wang@Sun.COM 
1637956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_read_wx(adapter, NX_CDRP_CRB_OFFSET,
1647956Sxiuyan.wang@Sun.COM 		    &raw_rsp, 4);
1657956Sxiuyan.wang@Sun.COM 
1667956Sxiuyan.wang@Sun.COM 		rsp = LE_TO_HOST_32(raw_rsp);
1677956Sxiuyan.wang@Sun.COM 	} while (!NX_CDRP_IS_RSP(rsp));
1687956Sxiuyan.wang@Sun.COM 
1697956Sxiuyan.wang@Sun.COM 	return (rsp);
1707956Sxiuyan.wang@Sun.COM }
1717956Sxiuyan.wang@Sun.COM 
1727956Sxiuyan.wang@Sun.COM static u32
netxen_issue_cmd(struct unm_adapter_s * adapter,u32 pci_fn,u32 version,u32 arg1,u32 arg2,u32 arg3,u32 cmd)1737956Sxiuyan.wang@Sun.COM netxen_issue_cmd(struct unm_adapter_s *adapter,
1747956Sxiuyan.wang@Sun.COM 	u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
1757956Sxiuyan.wang@Sun.COM {
1767956Sxiuyan.wang@Sun.COM 	u32 rsp;
1777956Sxiuyan.wang@Sun.COM 	u32 signature = 0;
1787956Sxiuyan.wang@Sun.COM 	u32 rcode = NX_RCODE_SUCCESS;
1797956Sxiuyan.wang@Sun.COM 
1807956Sxiuyan.wang@Sun.COM 	signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version);
1817956Sxiuyan.wang@Sun.COM 
1827956Sxiuyan.wang@Sun.COM 	/* Acquire semaphore before accessing CRB */
1837956Sxiuyan.wang@Sun.COM 	if (netxen_api_lock(adapter))
1847956Sxiuyan.wang@Sun.COM 		return (NX_RCODE_TIMEOUT);
1857956Sxiuyan.wang@Sun.COM 
1867956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, NX_SIGN_CRB_OFFSET,
1877956Sxiuyan.wang@Sun.COM 	    HOST_TO_LE_32(signature));
1887956Sxiuyan.wang@Sun.COM 
1897956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, NX_ARG1_CRB_OFFSET,
1907956Sxiuyan.wang@Sun.COM 	    HOST_TO_LE_32(arg1));
1917956Sxiuyan.wang@Sun.COM 
1927956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, NX_ARG2_CRB_OFFSET,
1937956Sxiuyan.wang@Sun.COM 	    HOST_TO_LE_32(arg2));
1947956Sxiuyan.wang@Sun.COM 
1957956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, NX_ARG3_CRB_OFFSET,
1967956Sxiuyan.wang@Sun.COM 	    HOST_TO_LE_32(arg3));
1977956Sxiuyan.wang@Sun.COM 
1987956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, NX_CDRP_CRB_OFFSET,
1997956Sxiuyan.wang@Sun.COM 	    HOST_TO_LE_32(NX_CDRP_FORM_CMD(cmd)));
2007956Sxiuyan.wang@Sun.COM 
2017956Sxiuyan.wang@Sun.COM 	rsp = netxen_poll_rsp(adapter);
2027956Sxiuyan.wang@Sun.COM 
2037956Sxiuyan.wang@Sun.COM 	if (rsp == NX_CDRP_RSP_TIMEOUT) {
2047956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s: card response timeout.\n",
2057956Sxiuyan.wang@Sun.COM 		    unm_nic_driver_name);
2067956Sxiuyan.wang@Sun.COM 
2077956Sxiuyan.wang@Sun.COM 		rcode = NX_RCODE_TIMEOUT;
2087956Sxiuyan.wang@Sun.COM 	} else if (rsp == NX_CDRP_RSP_FAIL) {
2097956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_read_wx(adapter, NX_ARG1_CRB_OFFSET,
2107956Sxiuyan.wang@Sun.COM 		    &rcode, 4);
2117956Sxiuyan.wang@Sun.COM 		rcode = LE_TO_HOST_32(rcode);
2127956Sxiuyan.wang@Sun.COM 
2137956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s: failed card response code:0x%x\n",
2147956Sxiuyan.wang@Sun.COM 		    unm_nic_driver_name, rcode);
2157956Sxiuyan.wang@Sun.COM 	}
2167956Sxiuyan.wang@Sun.COM 
2177956Sxiuyan.wang@Sun.COM 	/* Release semaphore */
2187956Sxiuyan.wang@Sun.COM 	netxen_api_unlock(adapter);
2197956Sxiuyan.wang@Sun.COM 
2207956Sxiuyan.wang@Sun.COM 	return (rcode);
2217956Sxiuyan.wang@Sun.COM }
2227956Sxiuyan.wang@Sun.COM 
2237956Sxiuyan.wang@Sun.COM int
nx_fw_cmd_set_mtu(struct unm_adapter_s * adapter,int mtu)2247956Sxiuyan.wang@Sun.COM nx_fw_cmd_set_mtu(struct unm_adapter_s *adapter, int mtu)
2257956Sxiuyan.wang@Sun.COM {
2267956Sxiuyan.wang@Sun.COM 	u32 rcode = NX_RCODE_SUCCESS;
2277956Sxiuyan.wang@Sun.COM 	struct unm_recv_context_s *recv_ctx = &adapter->recv_ctx[0];
2287956Sxiuyan.wang@Sun.COM 
2297956Sxiuyan.wang@Sun.COM 	if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
2307956Sxiuyan.wang@Sun.COM 		rcode = netxen_issue_cmd(adapter,
2317956Sxiuyan.wang@Sun.COM 		    adapter->ahw.pci_func,
2327956Sxiuyan.wang@Sun.COM 		    NXHAL_VERSION,
2337956Sxiuyan.wang@Sun.COM 		    recv_ctx->context_id,
2347956Sxiuyan.wang@Sun.COM 		    mtu,
2357956Sxiuyan.wang@Sun.COM 		    0,
2367956Sxiuyan.wang@Sun.COM 		    NX_CDRP_CMD_SET_MTU);
2377956Sxiuyan.wang@Sun.COM 
2387956Sxiuyan.wang@Sun.COM 	if (rcode != NX_RCODE_SUCCESS)
2397956Sxiuyan.wang@Sun.COM 		return (-EIO);
2407956Sxiuyan.wang@Sun.COM 
2417956Sxiuyan.wang@Sun.COM 	return (0);
2427956Sxiuyan.wang@Sun.COM }
2437956Sxiuyan.wang@Sun.COM 
2447956Sxiuyan.wang@Sun.COM static int
nx_fw_cmd_create_rx_ctx(struct unm_adapter_s * adapter)2457956Sxiuyan.wang@Sun.COM nx_fw_cmd_create_rx_ctx(struct unm_adapter_s *adapter)
2467956Sxiuyan.wang@Sun.COM {
2477956Sxiuyan.wang@Sun.COM 	unm_recv_context_t	*recv_ctx = &adapter->recv_ctx[0];
2487956Sxiuyan.wang@Sun.COM 	nx_hostrq_rx_ctx_t	*prq;
2497956Sxiuyan.wang@Sun.COM 	nx_cardrsp_rx_ctx_t	*prsp;
2507956Sxiuyan.wang@Sun.COM 	nx_hostrq_rds_ring_t	*prq_rds;
2517956Sxiuyan.wang@Sun.COM 	nx_hostrq_sds_ring_t	*prq_sds;
2527956Sxiuyan.wang@Sun.COM 	nx_cardrsp_rds_ring_t	*prsp_rds;
2537956Sxiuyan.wang@Sun.COM 	nx_cardrsp_sds_ring_t	*prsp_sds;
2547956Sxiuyan.wang@Sun.COM 	unm_rcv_desc_ctx_t	*rcv_desc;
2557956Sxiuyan.wang@Sun.COM 	ddi_dma_cookie_t	cookie;
2567956Sxiuyan.wang@Sun.COM 	ddi_dma_handle_t	rqdhdl, rsdhdl;
2577956Sxiuyan.wang@Sun.COM 	ddi_acc_handle_t	rqahdl, rsahdl;
2587956Sxiuyan.wang@Sun.COM 	uint64_t		hostrq_phys_addr, cardrsp_phys_addr;
2597956Sxiuyan.wang@Sun.COM 	u64			phys_addr;
2607956Sxiuyan.wang@Sun.COM 	u32			cap, reg;
2617956Sxiuyan.wang@Sun.COM 	size_t			rq_size, rsp_size;
2627956Sxiuyan.wang@Sun.COM 	void			*addr;
2637956Sxiuyan.wang@Sun.COM 	int			i, nrds_rings, nsds_rings, err;
2647956Sxiuyan.wang@Sun.COM 
2657956Sxiuyan.wang@Sun.COM 	/* only one sds ring for now */
2667956Sxiuyan.wang@Sun.COM 	nrds_rings = adapter->max_rds_rings;
2677956Sxiuyan.wang@Sun.COM 	nsds_rings = 1;
2687956Sxiuyan.wang@Sun.COM 
2697956Sxiuyan.wang@Sun.COM 	rq_size =
2707956Sxiuyan.wang@Sun.COM 	    SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings);
2717956Sxiuyan.wang@Sun.COM 	rsp_size =
2727956Sxiuyan.wang@Sun.COM 	    SIZEOF_CARDRSP_RX(nx_cardrsp_rx_ctx_t, nrds_rings, nsds_rings);
2737956Sxiuyan.wang@Sun.COM 
2747956Sxiuyan.wang@Sun.COM 	if (unm_pci_alloc_consistent(adapter, rq_size, (caddr_t *)&addr,
2757956Sxiuyan.wang@Sun.COM 	    &cookie, &rqdhdl, &rqahdl) != DDI_SUCCESS)
2767956Sxiuyan.wang@Sun.COM 		return (-ENOMEM);
2777956Sxiuyan.wang@Sun.COM 	hostrq_phys_addr = cookie.dmac_laddress;
2787956Sxiuyan.wang@Sun.COM 	prq = (nx_hostrq_rx_ctx_t *)addr;
2797956Sxiuyan.wang@Sun.COM 
2807956Sxiuyan.wang@Sun.COM 	if (unm_pci_alloc_consistent(adapter, rsp_size, (caddr_t *)&addr,
2817956Sxiuyan.wang@Sun.COM 	    &cookie, &rsdhdl, &rsahdl) != DDI_SUCCESS) {
2827956Sxiuyan.wang@Sun.COM 		err = -ENOMEM;
2837956Sxiuyan.wang@Sun.COM 		goto out_free_rq;
2847956Sxiuyan.wang@Sun.COM 	}
2857956Sxiuyan.wang@Sun.COM 	cardrsp_phys_addr = cookie.dmac_laddress;
2867956Sxiuyan.wang@Sun.COM 	prsp = (nx_cardrsp_rx_ctx_t *)addr;
2877956Sxiuyan.wang@Sun.COM 
2887956Sxiuyan.wang@Sun.COM 	prq->host_rsp_dma_addr = HOST_TO_LE_64(cardrsp_phys_addr);
2897956Sxiuyan.wang@Sun.COM 
2907956Sxiuyan.wang@Sun.COM 	cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
2917956Sxiuyan.wang@Sun.COM 	cap |= (NX_CAP0_JUMBO_CONTIGUOUS);
2927956Sxiuyan.wang@Sun.COM 
2937956Sxiuyan.wang@Sun.COM 	prq->capabilities[0] = HOST_TO_LE_32(cap);
2947956Sxiuyan.wang@Sun.COM 	prq->host_int_crb_mode =
2957956Sxiuyan.wang@Sun.COM 	    HOST_TO_LE_32(NX_HOST_INT_CRB_MODE_SHARED);
2967956Sxiuyan.wang@Sun.COM 	prq->host_rds_crb_mode =
2977956Sxiuyan.wang@Sun.COM 	    HOST_TO_LE_32(NX_HOST_RDS_CRB_MODE_UNIQUE);
2987956Sxiuyan.wang@Sun.COM 
2997956Sxiuyan.wang@Sun.COM 	prq->num_rds_rings = HOST_TO_LE_16(nrds_rings);
3007956Sxiuyan.wang@Sun.COM 	prq->num_sds_rings = HOST_TO_LE_16(nsds_rings);
3017956Sxiuyan.wang@Sun.COM 	prq->rds_ring_offset = 0;
3027956Sxiuyan.wang@Sun.COM 	prq->sds_ring_offset = prq->rds_ring_offset +
3037956Sxiuyan.wang@Sun.COM 	    (sizeof (nx_hostrq_rds_ring_t) * nrds_rings);
3047956Sxiuyan.wang@Sun.COM 
305*8687SJing.Xiong@Sun.COM 	prq_rds = (nx_hostrq_rds_ring_t *)(uintptr_t)((char *)prq +
306*8687SJing.Xiong@Sun.COM 	    sizeof (*prq) + prq->rds_ring_offset);
3077956Sxiuyan.wang@Sun.COM 
3087956Sxiuyan.wang@Sun.COM 	for (i = 0; i < nrds_rings; i++) {
3097956Sxiuyan.wang@Sun.COM 		rcv_desc = &recv_ctx->rcv_desc[i];
3107956Sxiuyan.wang@Sun.COM 
3117956Sxiuyan.wang@Sun.COM 		prq_rds[i].host_phys_addr = HOST_TO_LE_64(rcv_desc->phys_addr);
3127956Sxiuyan.wang@Sun.COM 		prq_rds[i].ring_size = HOST_TO_LE_32(rcv_desc->MaxRxDescCount);
3137956Sxiuyan.wang@Sun.COM 		prq_rds[i].ring_kind = HOST_TO_LE_32(i);
3147956Sxiuyan.wang@Sun.COM 		prq_rds[i].buff_size = HOST_TO_LE_64(rcv_desc->dma_size);
3157956Sxiuyan.wang@Sun.COM 	}
3167956Sxiuyan.wang@Sun.COM 
317*8687SJing.Xiong@Sun.COM 	prq_sds = (nx_hostrq_sds_ring_t *)(uintptr_t)((char *)prq +
318*8687SJing.Xiong@Sun.COM 	    sizeof (*prq) + prq->sds_ring_offset);
3197956Sxiuyan.wang@Sun.COM 
3207956Sxiuyan.wang@Sun.COM 	prq_sds[0].host_phys_addr =
3217956Sxiuyan.wang@Sun.COM 	    HOST_TO_LE_64(recv_ctx->rcvStatusDesc_physAddr);
3227956Sxiuyan.wang@Sun.COM 	prq_sds[0].ring_size = HOST_TO_LE_32(adapter->MaxRxDescCount);
3237956Sxiuyan.wang@Sun.COM 	/* only one msix vector for now */
3247956Sxiuyan.wang@Sun.COM 	prq_sds[0].msi_index = HOST_TO_LE_32(0);
3257956Sxiuyan.wang@Sun.COM 
3267956Sxiuyan.wang@Sun.COM 	/* now byteswap offsets */
3277956Sxiuyan.wang@Sun.COM 	prq->rds_ring_offset = HOST_TO_LE_32(prq->rds_ring_offset);
3287956Sxiuyan.wang@Sun.COM 	prq->sds_ring_offset = HOST_TO_LE_32(prq->sds_ring_offset);
3297956Sxiuyan.wang@Sun.COM 
3307956Sxiuyan.wang@Sun.COM 	phys_addr = hostrq_phys_addr;
3317956Sxiuyan.wang@Sun.COM 	err = netxen_issue_cmd(adapter,
3327956Sxiuyan.wang@Sun.COM 	    adapter->ahw.pci_func,
3337956Sxiuyan.wang@Sun.COM 	    NXHAL_VERSION,
3347956Sxiuyan.wang@Sun.COM 	    (u32)(phys_addr >> 32),
3357956Sxiuyan.wang@Sun.COM 	    (u32)(phys_addr & 0xffffffff),
3367956Sxiuyan.wang@Sun.COM 	    rq_size,
3377956Sxiuyan.wang@Sun.COM 	    NX_CDRP_CMD_CREATE_RX_CTX);
3387956Sxiuyan.wang@Sun.COM 	if (err) {
3397956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "Failed to create rx ctx in firmware%d\n",
3407956Sxiuyan.wang@Sun.COM 		    err);
3417956Sxiuyan.wang@Sun.COM 		goto out_free_rsp;
3427956Sxiuyan.wang@Sun.COM 	}
3437956Sxiuyan.wang@Sun.COM 
3447956Sxiuyan.wang@Sun.COM 
345*8687SJing.Xiong@Sun.COM 	prsp_rds = (nx_cardrsp_rds_ring_t *)(uintptr_t)((char *)prsp +
346*8687SJing.Xiong@Sun.COM 	    sizeof (*prsp) + prsp->rds_ring_offset);
3477956Sxiuyan.wang@Sun.COM 
3487956Sxiuyan.wang@Sun.COM 	for (i = 0; i < LE_TO_HOST_32(prsp->num_rds_rings); i++) {
3497956Sxiuyan.wang@Sun.COM 		rcv_desc = &recv_ctx->rcv_desc[i];
3507956Sxiuyan.wang@Sun.COM 
3517956Sxiuyan.wang@Sun.COM 		reg = LE_TO_HOST_32(prsp_rds[i].host_producer_crb);
3527956Sxiuyan.wang@Sun.COM 		rcv_desc->host_rx_producer = UNM_NIC_REG(reg - 0x200);
3537956Sxiuyan.wang@Sun.COM 	}
3547956Sxiuyan.wang@Sun.COM 
355*8687SJing.Xiong@Sun.COM 	prsp_sds = (nx_cardrsp_sds_ring_t *)(uintptr_t)((char *)prsp +
356*8687SJing.Xiong@Sun.COM 	    sizeof (*prsp) + prsp->sds_ring_offset);
3577956Sxiuyan.wang@Sun.COM 	reg = LE_TO_HOST_32(prsp_sds[0].host_consumer_crb);
3587956Sxiuyan.wang@Sun.COM 	recv_ctx->host_sds_consumer = UNM_NIC_REG(reg - 0x200);
3597956Sxiuyan.wang@Sun.COM 
3607956Sxiuyan.wang@Sun.COM 	reg = LE_TO_HOST_32(prsp_sds[0].interrupt_crb);
3617956Sxiuyan.wang@Sun.COM 	adapter->interrupt_crb = UNM_NIC_REG(reg - 0x200);
3627956Sxiuyan.wang@Sun.COM 
3637956Sxiuyan.wang@Sun.COM 	recv_ctx->state = LE_TO_HOST_32(prsp->host_ctx_state);
3647956Sxiuyan.wang@Sun.COM 	recv_ctx->context_id = LE_TO_HOST_16(prsp->context_id);
3657956Sxiuyan.wang@Sun.COM 	recv_ctx->virt_port = LE_TO_HOST_16(prsp->virt_port);
3667956Sxiuyan.wang@Sun.COM 
3677956Sxiuyan.wang@Sun.COM out_free_rsp:
3687956Sxiuyan.wang@Sun.COM 	unm_pci_free_consistent(&rsdhdl, &rsahdl);
3697956Sxiuyan.wang@Sun.COM out_free_rq:
3707956Sxiuyan.wang@Sun.COM 	unm_pci_free_consistent(&rqdhdl, &rqahdl);
3717956Sxiuyan.wang@Sun.COM 	return (err);
3727956Sxiuyan.wang@Sun.COM }
3737956Sxiuyan.wang@Sun.COM 
3747956Sxiuyan.wang@Sun.COM static void
nx_fw_cmd_destroy_rx_ctx(struct unm_adapter_s * adapter)3757956Sxiuyan.wang@Sun.COM nx_fw_cmd_destroy_rx_ctx(struct unm_adapter_s *adapter)
3767956Sxiuyan.wang@Sun.COM {
3777956Sxiuyan.wang@Sun.COM 	struct unm_recv_context_s *recv_ctx = &adapter->recv_ctx[0];
3787956Sxiuyan.wang@Sun.COM 
3797956Sxiuyan.wang@Sun.COM 	if (netxen_issue_cmd(adapter,
3807956Sxiuyan.wang@Sun.COM 	    adapter->ahw.pci_func,
3817956Sxiuyan.wang@Sun.COM 	    NXHAL_VERSION,
3827956Sxiuyan.wang@Sun.COM 	    recv_ctx->context_id,
3837956Sxiuyan.wang@Sun.COM 	    NX_DESTROY_CTX_RESET,
3847956Sxiuyan.wang@Sun.COM 	    0,
3857956Sxiuyan.wang@Sun.COM 	    NX_CDRP_CMD_DESTROY_RX_CTX)) {
3867956Sxiuyan.wang@Sun.COM 
3877956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s: Failed to destroy rx ctx in firmware\n",
3887956Sxiuyan.wang@Sun.COM 		    unm_nic_driver_name);
3897956Sxiuyan.wang@Sun.COM 	}
3907956Sxiuyan.wang@Sun.COM }
3917956Sxiuyan.wang@Sun.COM 
3927956Sxiuyan.wang@Sun.COM static int
nx_fw_cmd_create_tx_ctx(struct unm_adapter_s * adapter)3937956Sxiuyan.wang@Sun.COM nx_fw_cmd_create_tx_ctx(struct unm_adapter_s *adapter)
3947956Sxiuyan.wang@Sun.COM {
3957956Sxiuyan.wang@Sun.COM 	nx_hostrq_tx_ctx_t	*prq;
3967956Sxiuyan.wang@Sun.COM 	nx_hostrq_cds_ring_t	*prq_cds;
3977956Sxiuyan.wang@Sun.COM 	nx_cardrsp_tx_ctx_t	*prsp;
3987956Sxiuyan.wang@Sun.COM 	ddi_dma_cookie_t	cookie;
3997956Sxiuyan.wang@Sun.COM 	ddi_dma_handle_t	rqdhdl, rsdhdl;
4007956Sxiuyan.wang@Sun.COM 	ddi_acc_handle_t	rqahdl, rsahdl;
4017956Sxiuyan.wang@Sun.COM 	void			*rq_addr, *rsp_addr;
4027956Sxiuyan.wang@Sun.COM 	size_t			rq_size, rsp_size;
4037956Sxiuyan.wang@Sun.COM 	u32			temp;
4047956Sxiuyan.wang@Sun.COM 	int			err = 0;
4057956Sxiuyan.wang@Sun.COM 	u64			offset, phys_addr;
4067956Sxiuyan.wang@Sun.COM 	uint64_t		rq_phys_addr, rsp_phys_addr;
4077956Sxiuyan.wang@Sun.COM 
4087956Sxiuyan.wang@Sun.COM 	rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
4097956Sxiuyan.wang@Sun.COM 	if (unm_pci_alloc_consistent(adapter, rq_size, (caddr_t *)&rq_addr,
4107956Sxiuyan.wang@Sun.COM 	    &cookie, &rqdhdl, &rqahdl) != DDI_SUCCESS)
4117956Sxiuyan.wang@Sun.COM 		return (-ENOMEM);
4127956Sxiuyan.wang@Sun.COM 	rq_phys_addr = cookie.dmac_laddress;
4137956Sxiuyan.wang@Sun.COM 
4147956Sxiuyan.wang@Sun.COM 	rsp_size = SIZEOF_CARDRSP_TX(nx_cardrsp_tx_ctx_t);
4157956Sxiuyan.wang@Sun.COM 	if (unm_pci_alloc_consistent(adapter, rsp_size, (caddr_t *)&rsp_addr,
4167956Sxiuyan.wang@Sun.COM 	    &cookie, &rsdhdl, &rsahdl) != DDI_SUCCESS) {
4177956Sxiuyan.wang@Sun.COM 		err = -ENOMEM;
4187956Sxiuyan.wang@Sun.COM 		goto out_free_rq;
4197956Sxiuyan.wang@Sun.COM 	}
4207956Sxiuyan.wang@Sun.COM 	rsp_phys_addr = cookie.dmac_laddress;
4217956Sxiuyan.wang@Sun.COM 
4227956Sxiuyan.wang@Sun.COM 	(void) memset(rq_addr, 0, rq_size);
4237956Sxiuyan.wang@Sun.COM 	prq = (nx_hostrq_tx_ctx_t *)rq_addr;
4247956Sxiuyan.wang@Sun.COM 
4257956Sxiuyan.wang@Sun.COM 	(void) memset(rsp_addr, 0, rsp_size);
4267956Sxiuyan.wang@Sun.COM 	prsp = (nx_cardrsp_tx_ctx_t *)rsp_addr;
4277956Sxiuyan.wang@Sun.COM 
4287956Sxiuyan.wang@Sun.COM 	prq->host_rsp_dma_addr = HOST_TO_LE_64(rsp_phys_addr);
4297956Sxiuyan.wang@Sun.COM 
4307956Sxiuyan.wang@Sun.COM 	temp = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
4317956Sxiuyan.wang@Sun.COM 	prq->capabilities[0] = HOST_TO_LE_32(temp);
4327956Sxiuyan.wang@Sun.COM 
4337956Sxiuyan.wang@Sun.COM 	prq->host_int_crb_mode =
4347956Sxiuyan.wang@Sun.COM 	    HOST_TO_LE_32(NX_HOST_INT_CRB_MODE_SHARED);
4357956Sxiuyan.wang@Sun.COM 
4367956Sxiuyan.wang@Sun.COM 	prq->interrupt_ctl = 0;
4377956Sxiuyan.wang@Sun.COM 	prq->msi_index = 0;
4387956Sxiuyan.wang@Sun.COM 
4397956Sxiuyan.wang@Sun.COM 	prq->dummy_dma_addr = HOST_TO_LE_64(adapter->dummy_dma.phys_addr);
4407956Sxiuyan.wang@Sun.COM 
4417956Sxiuyan.wang@Sun.COM 	offset = adapter->ctxDesc_physAddr + sizeof (RingContext);
4427956Sxiuyan.wang@Sun.COM 	prq->cmd_cons_dma_addr = HOST_TO_LE_64(offset);
4437956Sxiuyan.wang@Sun.COM 
4447956Sxiuyan.wang@Sun.COM 	prq_cds = &prq->cds_ring;
4457956Sxiuyan.wang@Sun.COM 
4467956Sxiuyan.wang@Sun.COM 	prq_cds->host_phys_addr =
4477956Sxiuyan.wang@Sun.COM 	    HOST_TO_LE_64(adapter->ahw.cmdDesc_physAddr);
4487956Sxiuyan.wang@Sun.COM 
4497956Sxiuyan.wang@Sun.COM 	prq_cds->ring_size = HOST_TO_LE_32(adapter->MaxTxDescCount);
4507956Sxiuyan.wang@Sun.COM 
4517956Sxiuyan.wang@Sun.COM 	phys_addr = rq_phys_addr;
4527956Sxiuyan.wang@Sun.COM 	err = netxen_issue_cmd(adapter,
4537956Sxiuyan.wang@Sun.COM 	    adapter->ahw.pci_func,
4547956Sxiuyan.wang@Sun.COM 	    NXHAL_VERSION,
4557956Sxiuyan.wang@Sun.COM 	    (u32)(phys_addr >> 32),
4567956Sxiuyan.wang@Sun.COM 	    ((u32)phys_addr & 0xffffffff),
4577956Sxiuyan.wang@Sun.COM 	    rq_size,
4587956Sxiuyan.wang@Sun.COM 	    NX_CDRP_CMD_CREATE_TX_CTX);
4597956Sxiuyan.wang@Sun.COM 
4607956Sxiuyan.wang@Sun.COM 	if (err == NX_RCODE_SUCCESS) {
4617956Sxiuyan.wang@Sun.COM 		temp = LE_TO_HOST_32(prsp->cds_ring.host_producer_crb);
4627956Sxiuyan.wang@Sun.COM 		adapter->crb_addr_cmd_producer =
4637956Sxiuyan.wang@Sun.COM 		    UNM_NIC_REG(temp - 0x200);
4647956Sxiuyan.wang@Sun.COM #if 0
4657956Sxiuyan.wang@Sun.COM 		adapter->tx_state =
4667956Sxiuyan.wang@Sun.COM 		    LE_TO_HOST_32(prsp->host_ctx_state);
4677956Sxiuyan.wang@Sun.COM #endif
4687956Sxiuyan.wang@Sun.COM 		adapter->tx_context_id =
4697956Sxiuyan.wang@Sun.COM 		    LE_TO_HOST_16(prsp->context_id);
4707956Sxiuyan.wang@Sun.COM 	} else {
4717956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "Failed to create tx ctx in firmware%d\n",
4727956Sxiuyan.wang@Sun.COM 		    err);
4737956Sxiuyan.wang@Sun.COM 		err = -EIO;
4747956Sxiuyan.wang@Sun.COM 	}
4757956Sxiuyan.wang@Sun.COM 
4767956Sxiuyan.wang@Sun.COM 	unm_pci_free_consistent(&rsdhdl, &rsahdl);
4777956Sxiuyan.wang@Sun.COM 
4787956Sxiuyan.wang@Sun.COM out_free_rq:
4797956Sxiuyan.wang@Sun.COM 	unm_pci_free_consistent(&rqdhdl, &rqahdl);
4807956Sxiuyan.wang@Sun.COM 
4817956Sxiuyan.wang@Sun.COM 	return (err);
4827956Sxiuyan.wang@Sun.COM }
4837956Sxiuyan.wang@Sun.COM 
4847956Sxiuyan.wang@Sun.COM static void
nx_fw_cmd_destroy_tx_ctx(struct unm_adapter_s * adapter)4857956Sxiuyan.wang@Sun.COM nx_fw_cmd_destroy_tx_ctx(struct unm_adapter_s *adapter)
4867956Sxiuyan.wang@Sun.COM {
4877956Sxiuyan.wang@Sun.COM 	if (netxen_issue_cmd(adapter,
4887956Sxiuyan.wang@Sun.COM 	    adapter->ahw.pci_func,
4897956Sxiuyan.wang@Sun.COM 	    NXHAL_VERSION,
4907956Sxiuyan.wang@Sun.COM 	    adapter->tx_context_id,
4917956Sxiuyan.wang@Sun.COM 	    NX_DESTROY_CTX_RESET,
4927956Sxiuyan.wang@Sun.COM 	    0,
4937956Sxiuyan.wang@Sun.COM 	    NX_CDRP_CMD_DESTROY_TX_CTX)) {
4947956Sxiuyan.wang@Sun.COM 
4957956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s: Failed to destroy tx ctx in firmware\n",
4967956Sxiuyan.wang@Sun.COM 		    unm_nic_driver_name);
4977956Sxiuyan.wang@Sun.COM 	}
4987956Sxiuyan.wang@Sun.COM }
4997956Sxiuyan.wang@Sun.COM 
5007956Sxiuyan.wang@Sun.COM static u64 ctx_addr_sig_regs[][3] = {
5017956Sxiuyan.wang@Sun.COM 	{UNM_NIC_REG(0x188), UNM_NIC_REG(0x18c), UNM_NIC_REG(0x1c0)},
5027956Sxiuyan.wang@Sun.COM 	{UNM_NIC_REG(0x190), UNM_NIC_REG(0x194), UNM_NIC_REG(0x1c4)},
5037956Sxiuyan.wang@Sun.COM 	{UNM_NIC_REG(0x198), UNM_NIC_REG(0x19c), UNM_NIC_REG(0x1c8)},
5047956Sxiuyan.wang@Sun.COM 	{UNM_NIC_REG(0x1a0), UNM_NIC_REG(0x1a4), UNM_NIC_REG(0x1cc)}
5057956Sxiuyan.wang@Sun.COM };
5067956Sxiuyan.wang@Sun.COM 
5077956Sxiuyan.wang@Sun.COM #define	CRB_CTX_ADDR_REG_LO(FUNC_ID)	(ctx_addr_sig_regs[FUNC_ID][0])
5087956Sxiuyan.wang@Sun.COM #define	CRB_CTX_ADDR_REG_HI(FUNC_ID)	(ctx_addr_sig_regs[FUNC_ID][2])
5097956Sxiuyan.wang@Sun.COM #define	CRB_CTX_SIGNATURE_REG(FUNC_ID)	(ctx_addr_sig_regs[FUNC_ID][1])
5107956Sxiuyan.wang@Sun.COM 
5117956Sxiuyan.wang@Sun.COM struct netxen_recv_crb {
5127956Sxiuyan.wang@Sun.COM 	u32	crb_rcv_producer[NUM_RCV_DESC_RINGS];
5137956Sxiuyan.wang@Sun.COM 	u32	crb_sts_consumer;
5147956Sxiuyan.wang@Sun.COM };
5157956Sxiuyan.wang@Sun.COM 
5167956Sxiuyan.wang@Sun.COM static struct netxen_recv_crb recv_crb_registers[] = {
5177956Sxiuyan.wang@Sun.COM 	/* Instance 0 */
5187956Sxiuyan.wang@Sun.COM 	{
5197956Sxiuyan.wang@Sun.COM 		/* crb_rcv_producer: */
5207956Sxiuyan.wang@Sun.COM 		{
5217956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x100),
5227956Sxiuyan.wang@Sun.COM 			/* Jumbo frames */
5237956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x110),
5247956Sxiuyan.wang@Sun.COM 			/* LRO */
5257956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x120)
5267956Sxiuyan.wang@Sun.COM 		},
5277956Sxiuyan.wang@Sun.COM 		/* crb_sts_consumer: */
5287956Sxiuyan.wang@Sun.COM 		UNM_NIC_REG(0x138),
5297956Sxiuyan.wang@Sun.COM 	},
5307956Sxiuyan.wang@Sun.COM 	/* Instance 1 */
5317956Sxiuyan.wang@Sun.COM 	{
5327956Sxiuyan.wang@Sun.COM 		/* crb_rcv_producer: */
5337956Sxiuyan.wang@Sun.COM 		{
5347956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x144),
5357956Sxiuyan.wang@Sun.COM 			/* Jumbo frames */
5367956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x154),
5377956Sxiuyan.wang@Sun.COM 			/* LRO */
5387956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x164)
5397956Sxiuyan.wang@Sun.COM 		},
5407956Sxiuyan.wang@Sun.COM 		/* crb_sts_consumer: */
5417956Sxiuyan.wang@Sun.COM 		UNM_NIC_REG(0x17c),
5427956Sxiuyan.wang@Sun.COM 	},
5437956Sxiuyan.wang@Sun.COM 	/* Instance 2 */
5447956Sxiuyan.wang@Sun.COM 	{
5457956Sxiuyan.wang@Sun.COM 		/* crb_rcv_producer: */
5467956Sxiuyan.wang@Sun.COM 		{
5477956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x1d8),
5487956Sxiuyan.wang@Sun.COM 			/* Jumbo frames */
5497956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x1f8),
5507956Sxiuyan.wang@Sun.COM 			/* LRO */
5517956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x208)
5527956Sxiuyan.wang@Sun.COM 		},
5537956Sxiuyan.wang@Sun.COM 		/* crb_sts_consumer: */
5547956Sxiuyan.wang@Sun.COM 		UNM_NIC_REG(0x220),
5557956Sxiuyan.wang@Sun.COM 	},
5567956Sxiuyan.wang@Sun.COM 	/* Instance 3 */
5577956Sxiuyan.wang@Sun.COM 	{
5587956Sxiuyan.wang@Sun.COM 		/* crb_rcv_producer: */
5597956Sxiuyan.wang@Sun.COM 		{
5607956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x22c),
5617956Sxiuyan.wang@Sun.COM 			/* Jumbo frames */
5627956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x23c),
5637956Sxiuyan.wang@Sun.COM 			/* LRO */
5647956Sxiuyan.wang@Sun.COM 			UNM_NIC_REG(0x24c)
5657956Sxiuyan.wang@Sun.COM 		},
5667956Sxiuyan.wang@Sun.COM 		/* crb_sts_consumer: */
5677956Sxiuyan.wang@Sun.COM 		UNM_NIC_REG(0x264),
5687956Sxiuyan.wang@Sun.COM 	},
5697956Sxiuyan.wang@Sun.COM };
5707956Sxiuyan.wang@Sun.COM 
5717956Sxiuyan.wang@Sun.COM static uint32_t sw_int_mask[4] = {
5727956Sxiuyan.wang@Sun.COM 	CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
5737956Sxiuyan.wang@Sun.COM 	CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
5747956Sxiuyan.wang@Sun.COM };
5757956Sxiuyan.wang@Sun.COM 
5767956Sxiuyan.wang@Sun.COM static int
netxen_init_old_ctx(struct unm_adapter_s * adapter)5777956Sxiuyan.wang@Sun.COM netxen_init_old_ctx(struct unm_adapter_s *adapter)
5787956Sxiuyan.wang@Sun.COM {
5797956Sxiuyan.wang@Sun.COM 	hardware_context		*hw = &adapter->ahw;
5807956Sxiuyan.wang@Sun.COM 	struct unm_recv_context_s	*recv_ctx;
5817956Sxiuyan.wang@Sun.COM 	unm_rcv_desc_ctx_t		*rcv_desc;
5827956Sxiuyan.wang@Sun.COM 	int				ctx, ring, func_id = adapter->portnum;
5837956Sxiuyan.wang@Sun.COM 	unsigned int			temp;
5847956Sxiuyan.wang@Sun.COM 
5857956Sxiuyan.wang@Sun.COM 	adapter->ctxDesc->CmdRingAddrLo = hw->cmdDesc_physAddr & 0xffffffffUL;
5867956Sxiuyan.wang@Sun.COM 	adapter->ctxDesc->CmdRingAddrHi = ((U64)hw->cmdDesc_physAddr >> 32);
5877956Sxiuyan.wang@Sun.COM 	adapter->ctxDesc->CmdRingSize = adapter->MaxTxDescCount;
5887956Sxiuyan.wang@Sun.COM 
5897956Sxiuyan.wang@Sun.COM 	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
5907956Sxiuyan.wang@Sun.COM 		recv_ctx = &adapter->recv_ctx[ctx];
5917956Sxiuyan.wang@Sun.COM 
5927956Sxiuyan.wang@Sun.COM 		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
5937956Sxiuyan.wang@Sun.COM 			rcv_desc = &recv_ctx->rcv_desc[ring];
5947956Sxiuyan.wang@Sun.COM 
5957956Sxiuyan.wang@Sun.COM 			adapter->ctxDesc->RcvContext[ring].RcvRingAddrLo =
5967956Sxiuyan.wang@Sun.COM 			    rcv_desc->phys_addr & 0xffffffffUL;
5977956Sxiuyan.wang@Sun.COM 			adapter->ctxDesc->RcvContext[ring].RcvRingAddrHi =
5987956Sxiuyan.wang@Sun.COM 			    ((U64)rcv_desc->phys_addr>>32);
5997956Sxiuyan.wang@Sun.COM 			adapter->ctxDesc->RcvContext[ring].RcvRingSize =
6007956Sxiuyan.wang@Sun.COM 			    rcv_desc->MaxRxDescCount;
6017956Sxiuyan.wang@Sun.COM 
6027956Sxiuyan.wang@Sun.COM 			rcv_desc->host_rx_producer =
6037956Sxiuyan.wang@Sun.COM 			    recv_crb_registers[adapter->portnum].
6047956Sxiuyan.wang@Sun.COM 			    crb_rcv_producer[ring];
6057956Sxiuyan.wang@Sun.COM 		}
6067956Sxiuyan.wang@Sun.COM 
6077956Sxiuyan.wang@Sun.COM 		adapter->ctxDesc->StsRingAddrLo =
6087956Sxiuyan.wang@Sun.COM 		    recv_ctx->rcvStatusDesc_physAddr & 0xffffffff;
6097956Sxiuyan.wang@Sun.COM 		adapter->ctxDesc->StsRingAddrHi =
6107956Sxiuyan.wang@Sun.COM 		    recv_ctx->rcvStatusDesc_physAddr >> 32;
6117956Sxiuyan.wang@Sun.COM 		adapter->ctxDesc->StsRingSize = adapter->MaxRxDescCount;
6127956Sxiuyan.wang@Sun.COM 
6137956Sxiuyan.wang@Sun.COM 		recv_ctx->host_sds_consumer =
6147956Sxiuyan.wang@Sun.COM 		    recv_crb_registers[adapter->portnum].crb_sts_consumer;
6157956Sxiuyan.wang@Sun.COM 	}
6167956Sxiuyan.wang@Sun.COM 
6177956Sxiuyan.wang@Sun.COM 	adapter->interrupt_crb = sw_int_mask[adapter->portnum];
6187956Sxiuyan.wang@Sun.COM 
6197956Sxiuyan.wang@Sun.COM 	temp = lower32(adapter->ctxDesc_physAddr);
6207956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, CRB_CTX_ADDR_REG_LO(func_id),
6217956Sxiuyan.wang@Sun.COM 	    &temp, 4);
6227956Sxiuyan.wang@Sun.COM 	temp = upper32(adapter->ctxDesc_physAddr);
6237956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, CRB_CTX_ADDR_REG_HI(func_id),
6247956Sxiuyan.wang@Sun.COM 	    &temp, 4);
6257956Sxiuyan.wang@Sun.COM 	temp = UNM_CTX_SIGNATURE | func_id;
6267956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, CRB_CTX_SIGNATURE_REG(func_id),
6277956Sxiuyan.wang@Sun.COM 	    &temp, 4);
6287956Sxiuyan.wang@Sun.COM 
6297956Sxiuyan.wang@Sun.COM 	return (0);
6307956Sxiuyan.wang@Sun.COM }
6317956Sxiuyan.wang@Sun.COM 
6327956Sxiuyan.wang@Sun.COM void
netxen_destroy_rxtx(struct unm_adapter_s * adapter)6337956Sxiuyan.wang@Sun.COM netxen_destroy_rxtx(struct unm_adapter_s *adapter)
6347956Sxiuyan.wang@Sun.COM {
6357956Sxiuyan.wang@Sun.COM 	if (adapter->fw_major >= 4) {
6367956Sxiuyan.wang@Sun.COM 		nx_fw_cmd_destroy_tx_ctx(adapter);
6377956Sxiuyan.wang@Sun.COM 		nx_fw_cmd_destroy_rx_ctx(adapter);
6387956Sxiuyan.wang@Sun.COM 	}
6397956Sxiuyan.wang@Sun.COM }
6407956Sxiuyan.wang@Sun.COM 
6417956Sxiuyan.wang@Sun.COM int
netxen_create_rxtx(struct unm_adapter_s * adapter)6427956Sxiuyan.wang@Sun.COM netxen_create_rxtx(struct unm_adapter_s *adapter)
6437956Sxiuyan.wang@Sun.COM {
6447956Sxiuyan.wang@Sun.COM 	int	err;
6457956Sxiuyan.wang@Sun.COM 
6467956Sxiuyan.wang@Sun.COM 	if (adapter->fw_major >= 4) {
6477956Sxiuyan.wang@Sun.COM 		err = nx_fw_cmd_create_rx_ctx(adapter);
6487956Sxiuyan.wang@Sun.COM 		if (err)
6497956Sxiuyan.wang@Sun.COM 			return (err);
6507956Sxiuyan.wang@Sun.COM 		err = nx_fw_cmd_create_tx_ctx(adapter);
6517956Sxiuyan.wang@Sun.COM 		if (err)
6527956Sxiuyan.wang@Sun.COM 			nx_fw_cmd_destroy_rx_ctx(adapter);
6537956Sxiuyan.wang@Sun.COM 		return (err);
6547956Sxiuyan.wang@Sun.COM 	} else {
6557956Sxiuyan.wang@Sun.COM 		return (netxen_init_old_ctx(adapter));
6567956Sxiuyan.wang@Sun.COM 	}
6577956Sxiuyan.wang@Sun.COM }
658