xref: /onnv-gate/usr/src/uts/common/io/ntxn/unm_gem.c (revision 7956:59ff93e4da95)
1*7956Sxiuyan.wang@Sun.COM /*
2*7956Sxiuyan.wang@Sun.COM  * CDDL HEADER START
3*7956Sxiuyan.wang@Sun.COM  *
4*7956Sxiuyan.wang@Sun.COM  * The contents of this file are subject to the terms of the
5*7956Sxiuyan.wang@Sun.COM  * Common Development and Distribution License (the "License").
6*7956Sxiuyan.wang@Sun.COM  * You may not use this file except in compliance with the License.
7*7956Sxiuyan.wang@Sun.COM  *
8*7956Sxiuyan.wang@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7956Sxiuyan.wang@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7956Sxiuyan.wang@Sun.COM  * See the License for the specific language governing permissions
11*7956Sxiuyan.wang@Sun.COM  * and limitations under the License.
12*7956Sxiuyan.wang@Sun.COM  *
13*7956Sxiuyan.wang@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7956Sxiuyan.wang@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7956Sxiuyan.wang@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7956Sxiuyan.wang@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7956Sxiuyan.wang@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7956Sxiuyan.wang@Sun.COM  *
19*7956Sxiuyan.wang@Sun.COM  * CDDL HEADER END
20*7956Sxiuyan.wang@Sun.COM  */
21*7956Sxiuyan.wang@Sun.COM /*
22*7956Sxiuyan.wang@Sun.COM  * Copyright 2008 NetXen, Inc.  All rights reserved.
23*7956Sxiuyan.wang@Sun.COM  * Use is subject to license terms.
24*7956Sxiuyan.wang@Sun.COM  */
25*7956Sxiuyan.wang@Sun.COM /*
26*7956Sxiuyan.wang@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
27*7956Sxiuyan.wang@Sun.COM  * Use is subject to license terms.
28*7956Sxiuyan.wang@Sun.COM  */
29*7956Sxiuyan.wang@Sun.COM #include <sys/types.h>
30*7956Sxiuyan.wang@Sun.COM #include <sys/conf.h>
31*7956Sxiuyan.wang@Sun.COM #include <sys/debug.h>
32*7956Sxiuyan.wang@Sun.COM #include <sys/stropts.h>
33*7956Sxiuyan.wang@Sun.COM #include <sys/stream.h>
34*7956Sxiuyan.wang@Sun.COM #include <sys/strlog.h>
35*7956Sxiuyan.wang@Sun.COM #include <sys/kmem.h>
36*7956Sxiuyan.wang@Sun.COM #include <sys/stat.h>
37*7956Sxiuyan.wang@Sun.COM #include <sys/kstat.h>
38*7956Sxiuyan.wang@Sun.COM #include <sys/vtrace.h>
39*7956Sxiuyan.wang@Sun.COM #include <sys/dlpi.h>
40*7956Sxiuyan.wang@Sun.COM #include <sys/strsun.h>
41*7956Sxiuyan.wang@Sun.COM #include <sys/ethernet.h>
42*7956Sxiuyan.wang@Sun.COM #include <sys/modctl.h>
43*7956Sxiuyan.wang@Sun.COM #include <sys/errno.h>
44*7956Sxiuyan.wang@Sun.COM #include <sys/dditypes.h>
45*7956Sxiuyan.wang@Sun.COM #include <sys/ddi.h>
46*7956Sxiuyan.wang@Sun.COM #include <sys/sunddi.h>
47*7956Sxiuyan.wang@Sun.COM #include <sys/sysmacros.h>
48*7956Sxiuyan.wang@Sun.COM #include <sys/pci.h>
49*7956Sxiuyan.wang@Sun.COM #include <sys/ddi_intr.h>
50*7956Sxiuyan.wang@Sun.COM 
51*7956Sxiuyan.wang@Sun.COM #include "unm_nic.h"
52*7956Sxiuyan.wang@Sun.COM #include "unm_nic_hw.h"
53*7956Sxiuyan.wang@Sun.COM #include "unm_brdcfg.h"
54*7956Sxiuyan.wang@Sun.COM #include "nic_cmn.h"
55*7956Sxiuyan.wang@Sun.COM #include "nic_phan_reg.h"
56*7956Sxiuyan.wang@Sun.COM #include "unm_nic_ioctl.h"
57*7956Sxiuyan.wang@Sun.COM #include "nx_hw_pci_regs.h"
58*7956Sxiuyan.wang@Sun.COM 
59*7956Sxiuyan.wang@Sun.COM char ident[] = "Netxen nic driver v" UNM_NIC_VERSIONID;
60*7956Sxiuyan.wang@Sun.COM char unm_nic_driver_name[] = "ntxn";
61*7956Sxiuyan.wang@Sun.COM int verbmsg = 0;
62*7956Sxiuyan.wang@Sun.COM 
63*7956Sxiuyan.wang@Sun.COM static char txbcopythreshold_propname[] = "tx_bcopy_threshold";
64*7956Sxiuyan.wang@Sun.COM static char rxbcopythreshold_propname[] = "rx_bcopy_threshold";
65*7956Sxiuyan.wang@Sun.COM static char rxringsize_propname[] = "rx_ring_size";
66*7956Sxiuyan.wang@Sun.COM static char jumborxringsize_propname[] = "jumbo_rx_ring_size";
67*7956Sxiuyan.wang@Sun.COM static char txringsize_propname[] = "tx_ring_size";
68*7956Sxiuyan.wang@Sun.COM static char defaultmtu_propname[] = "default_mtu";
69*7956Sxiuyan.wang@Sun.COM static char dmesg_propname[] = "verbose_driver";
70*7956Sxiuyan.wang@Sun.COM 
71*7956Sxiuyan.wang@Sun.COM #define	STRUCT_COPY(a, b)	bcopy(&(b), &(a), sizeof (a))
72*7956Sxiuyan.wang@Sun.COM 
73*7956Sxiuyan.wang@Sun.COM extern int unm_register_mac(unm_adapter *adapter);
74*7956Sxiuyan.wang@Sun.COM extern void unm_fini_kstats(unm_adapter* adapter);
75*7956Sxiuyan.wang@Sun.COM extern void unm_nic_remove(unm_adapter *adapter);
76*7956Sxiuyan.wang@Sun.COM extern int unm_nic_suspend(unm_adapter *);
77*7956Sxiuyan.wang@Sun.COM extern uint_t unm_intr(caddr_t, caddr_t);
78*7956Sxiuyan.wang@Sun.COM 
79*7956Sxiuyan.wang@Sun.COM /* Data access requirements. */
80*7956Sxiuyan.wang@Sun.COM static struct ddi_device_acc_attr unm_dev_attr = {
81*7956Sxiuyan.wang@Sun.COM 	DDI_DEVICE_ATTR_V0,
82*7956Sxiuyan.wang@Sun.COM 	DDI_STRUCTURE_LE_ACC,
83*7956Sxiuyan.wang@Sun.COM 	DDI_STRICTORDER_ACC
84*7956Sxiuyan.wang@Sun.COM };
85*7956Sxiuyan.wang@Sun.COM 
86*7956Sxiuyan.wang@Sun.COM static struct ddi_device_acc_attr unm_buf_attr = {
87*7956Sxiuyan.wang@Sun.COM 	DDI_DEVICE_ATTR_V0,
88*7956Sxiuyan.wang@Sun.COM 	DDI_NEVERSWAP_ACC,
89*7956Sxiuyan.wang@Sun.COM 	DDI_STRICTORDER_ACC
90*7956Sxiuyan.wang@Sun.COM };
91*7956Sxiuyan.wang@Sun.COM 
92*7956Sxiuyan.wang@Sun.COM static ddi_dma_attr_t unm_dma_attr_desc = {
93*7956Sxiuyan.wang@Sun.COM 	DMA_ATTR_V0,		/* dma_attr_version */
94*7956Sxiuyan.wang@Sun.COM 	0,			/* dma_attr_addr_lo */
95*7956Sxiuyan.wang@Sun.COM 	0xffffffffull,		/* dma_attr_addr_hi */
96*7956Sxiuyan.wang@Sun.COM 	0x000fffffull,		/* dma_attr_count_max */
97*7956Sxiuyan.wang@Sun.COM 	4096,			/* dma_attr_align */
98*7956Sxiuyan.wang@Sun.COM 	0x000fffffull,		/* dma_attr_burstsizes */
99*7956Sxiuyan.wang@Sun.COM 	4,			/* dma_attr_minxfer */
100*7956Sxiuyan.wang@Sun.COM 	0x003fffffull,		/* dma_attr_maxxfer */
101*7956Sxiuyan.wang@Sun.COM 	0xffffffffull,		/* dma_attr_seg */
102*7956Sxiuyan.wang@Sun.COM 	1,			/* dma_attr_sgllen */
103*7956Sxiuyan.wang@Sun.COM 	1,			/* dma_attr_granular */
104*7956Sxiuyan.wang@Sun.COM 	0			/* dma_attr_flags */
105*7956Sxiuyan.wang@Sun.COM };
106*7956Sxiuyan.wang@Sun.COM 
107*7956Sxiuyan.wang@Sun.COM static ddi_dma_attr_t unm_dma_attr_rxbuf = {
108*7956Sxiuyan.wang@Sun.COM 	DMA_ATTR_V0,		/* dma_attr_version */
109*7956Sxiuyan.wang@Sun.COM 	0,			/* dma_attr_addr_lo */
110*7956Sxiuyan.wang@Sun.COM 	0x7ffffffffULL,		/* dma_attr_addr_hi */
111*7956Sxiuyan.wang@Sun.COM 	0xffffull,		/* dma_attr_count_max */
112*7956Sxiuyan.wang@Sun.COM 	4096,			/* dma_attr_align */
113*7956Sxiuyan.wang@Sun.COM 	0xfff8ull,		/* dma_attr_burstsizes */
114*7956Sxiuyan.wang@Sun.COM 	1,			/* dma_attr_minxfer */
115*7956Sxiuyan.wang@Sun.COM 	0xffffffffull,		/* dma_attr_maxxfer */
116*7956Sxiuyan.wang@Sun.COM 	0xffffull,		/* dma_attr_seg */
117*7956Sxiuyan.wang@Sun.COM 	1,			/* dma_attr_sgllen */
118*7956Sxiuyan.wang@Sun.COM 	1,			/* dma_attr_granular */
119*7956Sxiuyan.wang@Sun.COM 	0			/* dma_attr_flags */
120*7956Sxiuyan.wang@Sun.COM };
121*7956Sxiuyan.wang@Sun.COM 
122*7956Sxiuyan.wang@Sun.COM static ddi_dma_attr_t unm_dma_attr_cmddesc = {
123*7956Sxiuyan.wang@Sun.COM 	DMA_ATTR_V0,		/* dma_attr_version */
124*7956Sxiuyan.wang@Sun.COM 	0,			/* dma_attr_addr_lo */
125*7956Sxiuyan.wang@Sun.COM 	0x7ffffffffULL,		/* dma_attr_addr_hi */
126*7956Sxiuyan.wang@Sun.COM 	0xffffull,		/* dma_attr_count_max */
127*7956Sxiuyan.wang@Sun.COM 	1,			/* dma_attr_align */
128*7956Sxiuyan.wang@Sun.COM 	0xfff8ull,		/* dma_attr_burstsizes */
129*7956Sxiuyan.wang@Sun.COM 	1,			/* dma_attr_minxfer */
130*7956Sxiuyan.wang@Sun.COM 	0xffff0ull,		/* dma_attr_maxxfer */
131*7956Sxiuyan.wang@Sun.COM 	0xffffull,		/* dma_attr_seg */
132*7956Sxiuyan.wang@Sun.COM 	16,			/* dma_attr_sgllen */
133*7956Sxiuyan.wang@Sun.COM 	1,			/* dma_attr_granular */
134*7956Sxiuyan.wang@Sun.COM 	0			/* dma_attr_flags */
135*7956Sxiuyan.wang@Sun.COM };
136*7956Sxiuyan.wang@Sun.COM 
137*7956Sxiuyan.wang@Sun.COM static struct nx_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
138*7956Sxiuyan.wang@Sun.COM 
139*7956Sxiuyan.wang@Sun.COM static int
140*7956Sxiuyan.wang@Sun.COM check_hw_init(struct unm_adapter_s *adapter)
141*7956Sxiuyan.wang@Sun.COM {
142*7956Sxiuyan.wang@Sun.COM 	u32	val;
143*7956Sxiuyan.wang@Sun.COM 	int	ret = 0;
144*7956Sxiuyan.wang@Sun.COM 
145*7956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_read_wx(adapter, UNM_CAM_RAM(0x1fc), &val, 4);
146*7956Sxiuyan.wang@Sun.COM 	if (val == 0x55555555) {
147*7956Sxiuyan.wang@Sun.COM 		/* This is the first boot after power up */
148*7956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_read_wx(adapter, UNM_ROMUSB_GLB_SW_RESET,
149*7956Sxiuyan.wang@Sun.COM 		    &val, 4);
150*7956Sxiuyan.wang@Sun.COM 		if (val != 0x80000f)
151*7956Sxiuyan.wang@Sun.COM 			ret = -1;
152*7956Sxiuyan.wang@Sun.COM 
153*7956Sxiuyan.wang@Sun.COM 		if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
154*7956Sxiuyan.wang@Sun.COM 			/* Start P2 boot loader */
155*7956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_pci_write_normalize(adapter,
156*7956Sxiuyan.wang@Sun.COM 			    UNM_CAM_RAM(0x1fc), UNM_BDINFO_MAGIC);
157*7956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_pci_write_normalize(adapter,
158*7956Sxiuyan.wang@Sun.COM 			    UNM_ROMUSB_GLB_PEGTUNE_DONE, 1);
159*7956Sxiuyan.wang@Sun.COM 		}
160*7956Sxiuyan.wang@Sun.COM 	}
161*7956Sxiuyan.wang@Sun.COM 	return (ret);
162*7956Sxiuyan.wang@Sun.COM }
163*7956Sxiuyan.wang@Sun.COM 
164*7956Sxiuyan.wang@Sun.COM 
165*7956Sxiuyan.wang@Sun.COM static int
166*7956Sxiuyan.wang@Sun.COM unm_get_flash_block(unm_adapter *adapter, int base, int size, uint32_t *buf)
167*7956Sxiuyan.wang@Sun.COM {
168*7956Sxiuyan.wang@Sun.COM 	int i, addr;
169*7956Sxiuyan.wang@Sun.COM 	uint32_t *ptr32;
170*7956Sxiuyan.wang@Sun.COM 
171*7956Sxiuyan.wang@Sun.COM 	addr  = base;
172*7956Sxiuyan.wang@Sun.COM 	ptr32 = buf;
173*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < size / sizeof (uint32_t); i++) {
174*7956Sxiuyan.wang@Sun.COM 		if (rom_fast_read(adapter, addr, (int *)ptr32) == -1)
175*7956Sxiuyan.wang@Sun.COM 			return (-1);
176*7956Sxiuyan.wang@Sun.COM 		ptr32++;
177*7956Sxiuyan.wang@Sun.COM 		addr += sizeof (uint32_t);
178*7956Sxiuyan.wang@Sun.COM 	}
179*7956Sxiuyan.wang@Sun.COM 	if ((char *)buf + size > (char *)ptr32) {
180*7956Sxiuyan.wang@Sun.COM 		int local;
181*7956Sxiuyan.wang@Sun.COM 
182*7956Sxiuyan.wang@Sun.COM 		if (rom_fast_read(adapter, addr, &local) == -1)
183*7956Sxiuyan.wang@Sun.COM 			return (-1);
184*7956Sxiuyan.wang@Sun.COM 		(void) memcpy(ptr32, &local,
185*7956Sxiuyan.wang@Sun.COM 		    (uintptr_t)((char *)buf + size) - (uintptr_t)(char *)ptr32);
186*7956Sxiuyan.wang@Sun.COM 	}
187*7956Sxiuyan.wang@Sun.COM 
188*7956Sxiuyan.wang@Sun.COM 	return (0);
189*7956Sxiuyan.wang@Sun.COM }
190*7956Sxiuyan.wang@Sun.COM 
191*7956Sxiuyan.wang@Sun.COM 
192*7956Sxiuyan.wang@Sun.COM static int
193*7956Sxiuyan.wang@Sun.COM get_flash_mac_addr(struct unm_adapter_s *adapter, u64 mac[])
194*7956Sxiuyan.wang@Sun.COM {
195*7956Sxiuyan.wang@Sun.COM 	uint32_t *pmac = (uint32_t *)&mac[0];
196*7956Sxiuyan.wang@Sun.COM 
197*7956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
198*7956Sxiuyan.wang@Sun.COM 		uint32_t temp, crbaddr;
199*7956Sxiuyan.wang@Sun.COM 		uint16_t *pmac16 = (uint16_t *)pmac;
200*7956Sxiuyan.wang@Sun.COM 
201*7956Sxiuyan.wang@Sun.COM 		// FOR P3, read from CAM RAM
202*7956Sxiuyan.wang@Sun.COM 
203*7956Sxiuyan.wang@Sun.COM 		int pci_func = adapter->ahw.pci_func;
204*7956Sxiuyan.wang@Sun.COM 		pmac16 += (4*pci_func);
205*7956Sxiuyan.wang@Sun.COM 		crbaddr = CRB_MAC_BLOCK_START + (4 * ((pci_func/2) * 3)) +
206*7956Sxiuyan.wang@Sun.COM 		    (4 * (pci_func & 1));
207*7956Sxiuyan.wang@Sun.COM 
208*7956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_read_wx(adapter, crbaddr, &temp, 4);
209*7956Sxiuyan.wang@Sun.COM 		if (pci_func & 1) {
210*7956Sxiuyan.wang@Sun.COM 			*pmac16++ = (temp >> 16);
211*7956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_read_wx(adapter, crbaddr+4,
212*7956Sxiuyan.wang@Sun.COM 			    &temp, 4);
213*7956Sxiuyan.wang@Sun.COM 			*pmac16++ = (temp & 0xffff);
214*7956Sxiuyan.wang@Sun.COM 			*pmac16++ = (temp >> 16);
215*7956Sxiuyan.wang@Sun.COM 			*pmac16 = 0;
216*7956Sxiuyan.wang@Sun.COM 		} else {
217*7956Sxiuyan.wang@Sun.COM 			*pmac16++ = (temp & 0xffff);
218*7956Sxiuyan.wang@Sun.COM 			*pmac16++ = (temp >> 16);
219*7956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_read_wx(adapter, crbaddr+4,
220*7956Sxiuyan.wang@Sun.COM 			    &temp, 4);
221*7956Sxiuyan.wang@Sun.COM 			*pmac16++ = (temp & 0xffff);
222*7956Sxiuyan.wang@Sun.COM 			*pmac16 = 0;
223*7956Sxiuyan.wang@Sun.COM 		}
224*7956Sxiuyan.wang@Sun.COM 		return (0);
225*7956Sxiuyan.wang@Sun.COM 	}
226*7956Sxiuyan.wang@Sun.COM 
227*7956Sxiuyan.wang@Sun.COM 
228*7956Sxiuyan.wang@Sun.COM 	if (unm_get_flash_block(adapter, USER_START +
229*7956Sxiuyan.wang@Sun.COM 	    offsetof(unm_user_info_t, mac_addr), FLASH_NUM_PORTS * sizeof (U64),
230*7956Sxiuyan.wang@Sun.COM 	    pmac) == -1)
231*7956Sxiuyan.wang@Sun.COM 		return (-1);
232*7956Sxiuyan.wang@Sun.COM 
233*7956Sxiuyan.wang@Sun.COM 	if (*mac == ~0ULL) {
234*7956Sxiuyan.wang@Sun.COM 		if (unm_get_flash_block(adapter, USER_START_OLD +
235*7956Sxiuyan.wang@Sun.COM 		    offsetof(unm_old_user_info_t, mac_addr),
236*7956Sxiuyan.wang@Sun.COM 		    FLASH_NUM_PORTS * sizeof (U64), pmac) == -1)
237*7956Sxiuyan.wang@Sun.COM 			return (-1);
238*7956Sxiuyan.wang@Sun.COM 
239*7956Sxiuyan.wang@Sun.COM 		if (*mac == ~0ULL)
240*7956Sxiuyan.wang@Sun.COM 			return (-1);
241*7956Sxiuyan.wang@Sun.COM 	}
242*7956Sxiuyan.wang@Sun.COM 
243*7956Sxiuyan.wang@Sun.COM 	return (0);
244*7956Sxiuyan.wang@Sun.COM }
245*7956Sxiuyan.wang@Sun.COM 
246*7956Sxiuyan.wang@Sun.COM static int
247*7956Sxiuyan.wang@Sun.COM is_flash_supported(unm_adapter *adapter)
248*7956Sxiuyan.wang@Sun.COM {
249*7956Sxiuyan.wang@Sun.COM 	int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 };
250*7956Sxiuyan.wang@Sun.COM 	int addr, val01, val02, i, j;
251*7956Sxiuyan.wang@Sun.COM 
252*7956Sxiuyan.wang@Sun.COM 	/* if the flash size less than 4Mb, make huge war cry and die */
253*7956Sxiuyan.wang@Sun.COM 	for (j = 1; j < 4; j++) {
254*7956Sxiuyan.wang@Sun.COM 		addr = j * 0x100000;
255*7956Sxiuyan.wang@Sun.COM 		for (i = 0; i < (sizeof (locs) / sizeof (locs[0])); i++) {
256*7956Sxiuyan.wang@Sun.COM 			if (rom_fast_read(adapter, locs[i], &val01) == 0 &&
257*7956Sxiuyan.wang@Sun.COM 			    rom_fast_read(adapter, (addr + locs[i]),
258*7956Sxiuyan.wang@Sun.COM 			    &val02) == 0) {
259*7956Sxiuyan.wang@Sun.COM 				if (val01 == val02)
260*7956Sxiuyan.wang@Sun.COM 					return (-1);
261*7956Sxiuyan.wang@Sun.COM 			} else {
262*7956Sxiuyan.wang@Sun.COM 				return (-1);
263*7956Sxiuyan.wang@Sun.COM 			}
264*7956Sxiuyan.wang@Sun.COM 		}
265*7956Sxiuyan.wang@Sun.COM 	}
266*7956Sxiuyan.wang@Sun.COM 
267*7956Sxiuyan.wang@Sun.COM 	return (0);
268*7956Sxiuyan.wang@Sun.COM }
269*7956Sxiuyan.wang@Sun.COM 
270*7956Sxiuyan.wang@Sun.COM static int
271*7956Sxiuyan.wang@Sun.COM unm_initialize_dummy_dma(unm_adapter *adapter)
272*7956Sxiuyan.wang@Sun.COM {
273*7956Sxiuyan.wang@Sun.COM 	uint32_t		hi, lo, temp;
274*7956Sxiuyan.wang@Sun.COM 	ddi_dma_cookie_t	cookie;
275*7956Sxiuyan.wang@Sun.COM 
276*7956Sxiuyan.wang@Sun.COM 	if (unm_pci_alloc_consistent(adapter, UNM_HOST_DUMMY_DMA_SIZE,
277*7956Sxiuyan.wang@Sun.COM 	    (caddr_t *)&adapter->dummy_dma.addr, &cookie,
278*7956Sxiuyan.wang@Sun.COM 	    &adapter->dummy_dma.dma_handle,
279*7956Sxiuyan.wang@Sun.COM 	    &adapter->dummy_dma.acc_handle) != DDI_SUCCESS) {
280*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: Unable to alloc dummy dma buf\n",
281*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
282*7956Sxiuyan.wang@Sun.COM 		return (DDI_ENOMEM);
283*7956Sxiuyan.wang@Sun.COM 	}
284*7956Sxiuyan.wang@Sun.COM 
285*7956Sxiuyan.wang@Sun.COM 	adapter->dummy_dma.phys_addr = cookie.dmac_laddress;
286*7956Sxiuyan.wang@Sun.COM 
287*7956Sxiuyan.wang@Sun.COM 	hi = (adapter->dummy_dma.phys_addr >> 32) & 0xffffffff;
288*7956Sxiuyan.wang@Sun.COM 	lo = adapter->dummy_dma.phys_addr & 0xffffffff;
289*7956Sxiuyan.wang@Sun.COM 
290*7956Sxiuyan.wang@Sun.COM 	UNM_READ_LOCK(&adapter->adapter_lock);
291*7956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI,
292*7956Sxiuyan.wang@Sun.COM 	    &hi, 4);
293*7956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO,
294*7956Sxiuyan.wang@Sun.COM 	    &lo, 4);
295*7956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
296*7956Sxiuyan.wang@Sun.COM 		temp = DUMMY_BUF_INIT;
297*7956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF,
298*7956Sxiuyan.wang@Sun.COM 		    &temp, 4);
299*7956Sxiuyan.wang@Sun.COM 	}
300*7956Sxiuyan.wang@Sun.COM 	UNM_READ_UNLOCK(&adapter->adapter_lock);
301*7956Sxiuyan.wang@Sun.COM 
302*7956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
303*7956Sxiuyan.wang@Sun.COM }
304*7956Sxiuyan.wang@Sun.COM 
305*7956Sxiuyan.wang@Sun.COM void
306*7956Sxiuyan.wang@Sun.COM unm_free_dummy_dma(unm_adapter *adapter)
307*7956Sxiuyan.wang@Sun.COM {
308*7956Sxiuyan.wang@Sun.COM 	if (adapter->dummy_dma.addr) {
309*7956Sxiuyan.wang@Sun.COM 		unm_pci_free_consistent(&adapter->dummy_dma.dma_handle,
310*7956Sxiuyan.wang@Sun.COM 		    &adapter->dummy_dma.acc_handle);
311*7956Sxiuyan.wang@Sun.COM 		adapter->dummy_dma.addr = NULL;
312*7956Sxiuyan.wang@Sun.COM 	}
313*7956Sxiuyan.wang@Sun.COM }
314*7956Sxiuyan.wang@Sun.COM 
315*7956Sxiuyan.wang@Sun.COM static int
316*7956Sxiuyan.wang@Sun.COM unm_pci_cfg_init(unm_adapter *adapter)
317*7956Sxiuyan.wang@Sun.COM {
318*7956Sxiuyan.wang@Sun.COM 	hardware_context *hwcontext;
319*7956Sxiuyan.wang@Sun.COM 	ddi_acc_handle_t pci_cfg_hdl;
320*7956Sxiuyan.wang@Sun.COM 	int *reg_options;
321*7956Sxiuyan.wang@Sun.COM 	dev_info_t *dip;
322*7956Sxiuyan.wang@Sun.COM 	uint_t noptions;
323*7956Sxiuyan.wang@Sun.COM 	int ret;
324*7956Sxiuyan.wang@Sun.COM 	uint16_t vendor_id, pci_cmd_word;
325*7956Sxiuyan.wang@Sun.COM 	uint8_t	base_class, sub_class, prog_class;
326*7956Sxiuyan.wang@Sun.COM 	uint32_t pexsizes;
327*7956Sxiuyan.wang@Sun.COM 	struct nx_legacy_intr_set *legacy_intrp;
328*7956Sxiuyan.wang@Sun.COM 
329*7956Sxiuyan.wang@Sun.COM 	hwcontext = &adapter->ahw;
330*7956Sxiuyan.wang@Sun.COM 	pci_cfg_hdl = adapter->pci_cfg_handle;
331*7956Sxiuyan.wang@Sun.COM 	dip = adapter->dip;
332*7956Sxiuyan.wang@Sun.COM 
333*7956Sxiuyan.wang@Sun.COM 	vendor_id = pci_config_get16(pci_cfg_hdl, PCI_CONF_VENID);
334*7956Sxiuyan.wang@Sun.COM 
335*7956Sxiuyan.wang@Sun.COM 	if (vendor_id != 0x4040) {
336*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: vendor id %x not 0x4040\n",
337*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance, vendor_id);
338*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
339*7956Sxiuyan.wang@Sun.COM 	}
340*7956Sxiuyan.wang@Sun.COM 
341*7956Sxiuyan.wang@Sun.COM 	ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
342*7956Sxiuyan.wang@Sun.COM 	    dip, 0, "reg", &reg_options, &noptions);
343*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_PROP_SUCCESS) {
344*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: Could not determine reg property\n",
345*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
346*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
347*7956Sxiuyan.wang@Sun.COM 	}
348*7956Sxiuyan.wang@Sun.COM 
349*7956Sxiuyan.wang@Sun.COM 	hwcontext->pci_func = (reg_options[0] >> 8) & 0x7;
350*7956Sxiuyan.wang@Sun.COM 	ddi_prop_free(reg_options);
351*7956Sxiuyan.wang@Sun.COM 
352*7956Sxiuyan.wang@Sun.COM 	base_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_BASCLASS);
353*7956Sxiuyan.wang@Sun.COM 	sub_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_SUBCLASS);
354*7956Sxiuyan.wang@Sun.COM 	prog_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_PROGCLASS);
355*7956Sxiuyan.wang@Sun.COM 
356*7956Sxiuyan.wang@Sun.COM 	/*
357*7956Sxiuyan.wang@Sun.COM 	 * Need this check so that MEZZ card mgmt interface ntxn0 could fail
358*7956Sxiuyan.wang@Sun.COM 	 * attach & return and proceed to next interfaces ntxn1 and ntxn2
359*7956Sxiuyan.wang@Sun.COM 	 */
360*7956Sxiuyan.wang@Sun.COM 	if ((base_class != 0x02) || (sub_class != 0) || (prog_class != 0)) {
361*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: Base/sub/prog class problem %d/%d/%d\n",
362*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance, base_class, sub_class,
363*7956Sxiuyan.wang@Sun.COM 		    prog_class);
364*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
365*7956Sxiuyan.wang@Sun.COM 	}
366*7956Sxiuyan.wang@Sun.COM 
367*7956Sxiuyan.wang@Sun.COM 	hwcontext->revision_id = pci_config_get8(pci_cfg_hdl, PCI_CONF_REVID);
368*7956Sxiuyan.wang@Sun.COM 
369*7956Sxiuyan.wang@Sun.COM 	/*
370*7956Sxiuyan.wang@Sun.COM 	 * Refuse to work with dubious P3 cards.
371*7956Sxiuyan.wang@Sun.COM 	 */
372*7956Sxiuyan.wang@Sun.COM 	if ((hwcontext->revision_id >= NX_P3_A0) &&
373*7956Sxiuyan.wang@Sun.COM 	    (hwcontext->revision_id < NX_P3_B1)) {
374*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: NetXen chip revs between 0x%x-0x%x "
375*7956Sxiuyan.wang@Sun.COM 		    "is unsupported\n", adapter->name, adapter->instance,
376*7956Sxiuyan.wang@Sun.COM 		    NX_P3_A0, NX_P3_B0);
377*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
378*7956Sxiuyan.wang@Sun.COM 	}
379*7956Sxiuyan.wang@Sun.COM 
380*7956Sxiuyan.wang@Sun.COM 	/*
381*7956Sxiuyan.wang@Sun.COM 	 * Save error reporting settings; clear [19:16] error status bits.
382*7956Sxiuyan.wang@Sun.COM 	 * Set max read request [14:12] to 0 for 128 bytes. Set max payload
383*7956Sxiuyan.wang@Sun.COM 	 * size[7:5] to 0 for for 128 bytes.
384*7956Sxiuyan.wang@Sun.COM 	 */
385*7956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P2(hwcontext->revision_id)) {
386*7956Sxiuyan.wang@Sun.COM 		pexsizes = pci_config_get32(pci_cfg_hdl, 0xd8);
387*7956Sxiuyan.wang@Sun.COM 		pexsizes &= 7;
388*7956Sxiuyan.wang@Sun.COM 		pexsizes |= 0xF0000;
389*7956Sxiuyan.wang@Sun.COM 		pci_config_put32(pci_cfg_hdl, 0xd8, pexsizes);
390*7956Sxiuyan.wang@Sun.COM 	}
391*7956Sxiuyan.wang@Sun.COM 
392*7956Sxiuyan.wang@Sun.COM 	pci_cmd_word = pci_config_get16(pci_cfg_hdl, PCI_CONF_COMM);
393*7956Sxiuyan.wang@Sun.COM 	pci_cmd_word |= (PCI_COMM_INTX_DISABLE | PCI_COMM_SERR_ENABLE);
394*7956Sxiuyan.wang@Sun.COM 	pci_config_put16(pci_cfg_hdl, PCI_CONF_COMM, pci_cmd_word);
395*7956Sxiuyan.wang@Sun.COM 
396*7956Sxiuyan.wang@Sun.COM 	if (hwcontext->revision_id >= NX_P3_B0)
397*7956Sxiuyan.wang@Sun.COM 		legacy_intrp = &legacy_intr[hwcontext->pci_func];
398*7956Sxiuyan.wang@Sun.COM 	else
399*7956Sxiuyan.wang@Sun.COM 		legacy_intrp = &legacy_intr[0];
400*7956Sxiuyan.wang@Sun.COM 
401*7956Sxiuyan.wang@Sun.COM 	adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit;
402*7956Sxiuyan.wang@Sun.COM 	adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg;
403*7956Sxiuyan.wang@Sun.COM 	adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg;
404*7956Sxiuyan.wang@Sun.COM 	adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg;
405*7956Sxiuyan.wang@Sun.COM 
406*7956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
407*7956Sxiuyan.wang@Sun.COM }
408*7956Sxiuyan.wang@Sun.COM 
409*7956Sxiuyan.wang@Sun.COM void
410*7956Sxiuyan.wang@Sun.COM unm_free_tx_dmahdl(unm_adapter *adapter)
411*7956Sxiuyan.wang@Sun.COM {
412*7956Sxiuyan.wang@Sun.COM 	int i;
413*7956Sxiuyan.wang@Sun.COM 	unm_dmah_node_t	 *nodep;
414*7956Sxiuyan.wang@Sun.COM 
415*7956Sxiuyan.wang@Sun.COM 	mutex_enter(&adapter->tx_lock);
416*7956Sxiuyan.wang@Sun.COM 	nodep = &adapter->tx_dma_hdls[0];
417*7956Sxiuyan.wang@Sun.COM 
418*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < adapter->MaxTxDescCount + EXTRA_HANDLES; i++) {
419*7956Sxiuyan.wang@Sun.COM 		if (nodep->dmahdl != NULL) {
420*7956Sxiuyan.wang@Sun.COM 			ddi_dma_free_handle(&nodep->dmahdl);
421*7956Sxiuyan.wang@Sun.COM 			nodep->dmahdl = NULL;
422*7956Sxiuyan.wang@Sun.COM 		}
423*7956Sxiuyan.wang@Sun.COM 		nodep->next = NULL;
424*7956Sxiuyan.wang@Sun.COM 		nodep++;
425*7956Sxiuyan.wang@Sun.COM 	}
426*7956Sxiuyan.wang@Sun.COM 
427*7956Sxiuyan.wang@Sun.COM 	adapter->dmahdl_pool = NULL;
428*7956Sxiuyan.wang@Sun.COM 	adapter->freehdls = 0;
429*7956Sxiuyan.wang@Sun.COM 	mutex_exit(&adapter->tx_lock);
430*7956Sxiuyan.wang@Sun.COM }
431*7956Sxiuyan.wang@Sun.COM 
432*7956Sxiuyan.wang@Sun.COM static int
433*7956Sxiuyan.wang@Sun.COM unm_alloc_tx_dmahdl(unm_adapter *adapter)
434*7956Sxiuyan.wang@Sun.COM {
435*7956Sxiuyan.wang@Sun.COM 	int		i;
436*7956Sxiuyan.wang@Sun.COM 	unm_dmah_node_t	*nodep = &adapter->tx_dma_hdls[0];
437*7956Sxiuyan.wang@Sun.COM 
438*7956Sxiuyan.wang@Sun.COM 	mutex_enter(&adapter->tx_lock);
439*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < adapter->MaxTxDescCount + EXTRA_HANDLES; i++) {
440*7956Sxiuyan.wang@Sun.COM 		if (ddi_dma_alloc_handle(adapter->dip, &unm_dma_attr_cmddesc,
441*7956Sxiuyan.wang@Sun.COM 		    DDI_DMA_DONTWAIT, NULL, &nodep->dmahdl) != DDI_SUCCESS) {
442*7956Sxiuyan.wang@Sun.COM 			mutex_exit(&adapter->tx_lock);
443*7956Sxiuyan.wang@Sun.COM 			goto alloc_hdl_fail;
444*7956Sxiuyan.wang@Sun.COM 		}
445*7956Sxiuyan.wang@Sun.COM 
446*7956Sxiuyan.wang@Sun.COM 		if (i > 0)
447*7956Sxiuyan.wang@Sun.COM 			nodep->next = nodep - 1;
448*7956Sxiuyan.wang@Sun.COM 		nodep++;
449*7956Sxiuyan.wang@Sun.COM 	}
450*7956Sxiuyan.wang@Sun.COM 
451*7956Sxiuyan.wang@Sun.COM 	adapter->dmahdl_pool = nodep - 1;
452*7956Sxiuyan.wang@Sun.COM 	adapter->freehdls = i;
453*7956Sxiuyan.wang@Sun.COM 	mutex_exit(&adapter->tx_lock);
454*7956Sxiuyan.wang@Sun.COM 
455*7956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
456*7956Sxiuyan.wang@Sun.COM 
457*7956Sxiuyan.wang@Sun.COM alloc_hdl_fail:
458*7956Sxiuyan.wang@Sun.COM 	unm_free_tx_dmahdl(adapter);
459*7956Sxiuyan.wang@Sun.COM 	cmn_err(CE_WARN, "%s%d: Failed transmit ring dma handle allocation\n",
460*7956Sxiuyan.wang@Sun.COM 	    adapter->name, adapter->instance);
461*7956Sxiuyan.wang@Sun.COM 	return (DDI_FAILURE);
462*7956Sxiuyan.wang@Sun.COM }
463*7956Sxiuyan.wang@Sun.COM 
464*7956Sxiuyan.wang@Sun.COM static void
465*7956Sxiuyan.wang@Sun.COM unm_free_dma_mem(dma_area_t *dma_p)
466*7956Sxiuyan.wang@Sun.COM {
467*7956Sxiuyan.wang@Sun.COM 	if (dma_p->dma_hdl != NULL) {
468*7956Sxiuyan.wang@Sun.COM 		if (dma_p->ncookies) {
469*7956Sxiuyan.wang@Sun.COM 			(void) ddi_dma_unbind_handle(dma_p->dma_hdl);
470*7956Sxiuyan.wang@Sun.COM 			dma_p->ncookies = 0;
471*7956Sxiuyan.wang@Sun.COM 		}
472*7956Sxiuyan.wang@Sun.COM 	}
473*7956Sxiuyan.wang@Sun.COM 	if (dma_p->acc_hdl != NULL) {
474*7956Sxiuyan.wang@Sun.COM 		ddi_dma_mem_free(&dma_p->acc_hdl);
475*7956Sxiuyan.wang@Sun.COM 		dma_p->acc_hdl = NULL;
476*7956Sxiuyan.wang@Sun.COM 	}
477*7956Sxiuyan.wang@Sun.COM 	if (dma_p->dma_hdl != NULL) {
478*7956Sxiuyan.wang@Sun.COM 		ddi_dma_free_handle(&dma_p->dma_hdl);
479*7956Sxiuyan.wang@Sun.COM 		dma_p->dma_hdl = NULL;
480*7956Sxiuyan.wang@Sun.COM 	}
481*7956Sxiuyan.wang@Sun.COM }
482*7956Sxiuyan.wang@Sun.COM 
483*7956Sxiuyan.wang@Sun.COM static int
484*7956Sxiuyan.wang@Sun.COM unm_alloc_dma_mem(unm_adapter *adapter, int size, uint_t dma_flag,
485*7956Sxiuyan.wang@Sun.COM 	ddi_dma_attr_t *dma_attr_p, dma_area_t *dma_p)
486*7956Sxiuyan.wang@Sun.COM {
487*7956Sxiuyan.wang@Sun.COM 	int ret;
488*7956Sxiuyan.wang@Sun.COM 	caddr_t vaddr;
489*7956Sxiuyan.wang@Sun.COM 	size_t actual_size;
490*7956Sxiuyan.wang@Sun.COM 	ddi_dma_cookie_t	cookie;
491*7956Sxiuyan.wang@Sun.COM 
492*7956Sxiuyan.wang@Sun.COM 	ret = ddi_dma_alloc_handle(adapter->dip,
493*7956Sxiuyan.wang@Sun.COM 	    dma_attr_p, DDI_DMA_DONTWAIT,
494*7956Sxiuyan.wang@Sun.COM 	    NULL, &dma_p->dma_hdl);
495*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
496*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: Failed ddi_dma_alloc_handle\n",
497*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
498*7956Sxiuyan.wang@Sun.COM 		goto dma_mem_fail;
499*7956Sxiuyan.wang@Sun.COM 	}
500*7956Sxiuyan.wang@Sun.COM 
501*7956Sxiuyan.wang@Sun.COM 	ret = ddi_dma_mem_alloc(dma_p->dma_hdl,
502*7956Sxiuyan.wang@Sun.COM 	    size, &adapter->gc_attr_desc,
503*7956Sxiuyan.wang@Sun.COM 	    dma_flag & (DDI_DMA_STREAMING | DDI_DMA_CONSISTENT),
504*7956Sxiuyan.wang@Sun.COM 	    DDI_DMA_DONTWAIT, NULL, &vaddr, &actual_size,
505*7956Sxiuyan.wang@Sun.COM 	    &dma_p->acc_hdl);
506*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
507*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: ddi_dma_mem_alloc() failed\n",
508*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
509*7956Sxiuyan.wang@Sun.COM 		goto dma_mem_fail;
510*7956Sxiuyan.wang@Sun.COM 	}
511*7956Sxiuyan.wang@Sun.COM 
512*7956Sxiuyan.wang@Sun.COM 	if (actual_size < size) {
513*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: ddi_dma_mem_alloc() allocated small\n",
514*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
515*7956Sxiuyan.wang@Sun.COM 		goto dma_mem_fail;
516*7956Sxiuyan.wang@Sun.COM 	}
517*7956Sxiuyan.wang@Sun.COM 
518*7956Sxiuyan.wang@Sun.COM 	ret = ddi_dma_addr_bind_handle(dma_p->dma_hdl,
519*7956Sxiuyan.wang@Sun.COM 	    NULL, vaddr, size, dma_flag, DDI_DMA_DONTWAIT,
520*7956Sxiuyan.wang@Sun.COM 	    NULL, &cookie, &dma_p->ncookies);
521*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_DMA_MAPPED || dma_p->ncookies != 1) {
522*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: ddi_dma_addr_bind_handle() failed, "
523*7956Sxiuyan.wang@Sun.COM 		    "%d, %d\n", adapter->name, adapter->instance, ret,
524*7956Sxiuyan.wang@Sun.COM 		    dma_p->ncookies);
525*7956Sxiuyan.wang@Sun.COM 		goto dma_mem_fail;
526*7956Sxiuyan.wang@Sun.COM 	}
527*7956Sxiuyan.wang@Sun.COM 
528*7956Sxiuyan.wang@Sun.COM 	dma_p->dma_addr = cookie.dmac_laddress;
529*7956Sxiuyan.wang@Sun.COM 	dma_p->vaddr = vaddr;
530*7956Sxiuyan.wang@Sun.COM 	(void) memset(vaddr, 0, size);
531*7956Sxiuyan.wang@Sun.COM 
532*7956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
533*7956Sxiuyan.wang@Sun.COM 
534*7956Sxiuyan.wang@Sun.COM dma_mem_fail:
535*7956Sxiuyan.wang@Sun.COM 	unm_free_dma_mem(dma_p);
536*7956Sxiuyan.wang@Sun.COM 	return (DDI_FAILURE);
537*7956Sxiuyan.wang@Sun.COM }
538*7956Sxiuyan.wang@Sun.COM 
539*7956Sxiuyan.wang@Sun.COM void
540*7956Sxiuyan.wang@Sun.COM unm_free_tx_buffers(unm_adapter *adapter)
541*7956Sxiuyan.wang@Sun.COM {
542*7956Sxiuyan.wang@Sun.COM 	int i;
543*7956Sxiuyan.wang@Sun.COM 	dma_area_t *dma_p;
544*7956Sxiuyan.wang@Sun.COM 	struct unm_cmd_buffer *cmd_buf;
545*7956Sxiuyan.wang@Sun.COM 	unm_dmah_node_t	 *nodep;
546*7956Sxiuyan.wang@Sun.COM 
547*7956Sxiuyan.wang@Sun.COM 	cmd_buf = &adapter->cmd_buf_arr[0];
548*7956Sxiuyan.wang@Sun.COM 
549*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < adapter->MaxTxDescCount; i++) {
550*7956Sxiuyan.wang@Sun.COM 		dma_p = &cmd_buf->dma_area;
551*7956Sxiuyan.wang@Sun.COM 		unm_free_dma_mem(dma_p);
552*7956Sxiuyan.wang@Sun.COM 		nodep = cmd_buf->head;
553*7956Sxiuyan.wang@Sun.COM 		while (nodep != NULL) {
554*7956Sxiuyan.wang@Sun.COM 			(void) ddi_dma_unbind_handle(nodep->dmahdl);
555*7956Sxiuyan.wang@Sun.COM 			nodep = nodep->next;
556*7956Sxiuyan.wang@Sun.COM 		}
557*7956Sxiuyan.wang@Sun.COM 		if (cmd_buf->msg != NULL)
558*7956Sxiuyan.wang@Sun.COM 			freemsg(cmd_buf->msg);
559*7956Sxiuyan.wang@Sun.COM 		cmd_buf++;
560*7956Sxiuyan.wang@Sun.COM 	}
561*7956Sxiuyan.wang@Sun.COM 	adapter->freecmds = 0;
562*7956Sxiuyan.wang@Sun.COM }
563*7956Sxiuyan.wang@Sun.COM 
564*7956Sxiuyan.wang@Sun.COM static int
565*7956Sxiuyan.wang@Sun.COM unm_alloc_tx_buffers(unm_adapter *adapter)
566*7956Sxiuyan.wang@Sun.COM {
567*7956Sxiuyan.wang@Sun.COM 	int i, ret, size, allocated = 0;
568*7956Sxiuyan.wang@Sun.COM 	dma_area_t *dma_p;
569*7956Sxiuyan.wang@Sun.COM 	struct unm_cmd_buffer *cmd_buf;
570*7956Sxiuyan.wang@Sun.COM 
571*7956Sxiuyan.wang@Sun.COM 	cmd_buf = &adapter->cmd_buf_arr[0];
572*7956Sxiuyan.wang@Sun.COM 	size = adapter->maxmtu;
573*7956Sxiuyan.wang@Sun.COM 
574*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < adapter->MaxTxDescCount; i++) {
575*7956Sxiuyan.wang@Sun.COM 		dma_p = &cmd_buf->dma_area;
576*7956Sxiuyan.wang@Sun.COM 		ret = unm_alloc_dma_mem(adapter, size,
577*7956Sxiuyan.wang@Sun.COM 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
578*7956Sxiuyan.wang@Sun.COM 		    &unm_dma_attr_rxbuf, dma_p);
579*7956Sxiuyan.wang@Sun.COM 		if (ret != DDI_SUCCESS)
580*7956Sxiuyan.wang@Sun.COM 			goto alloc_tx_buffer_fail;
581*7956Sxiuyan.wang@Sun.COM 
582*7956Sxiuyan.wang@Sun.COM 		allocated++;
583*7956Sxiuyan.wang@Sun.COM 		cmd_buf++;
584*7956Sxiuyan.wang@Sun.COM 	}
585*7956Sxiuyan.wang@Sun.COM 	adapter->freecmds = adapter->MaxTxDescCount;
586*7956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
587*7956Sxiuyan.wang@Sun.COM 
588*7956Sxiuyan.wang@Sun.COM alloc_tx_buffer_fail:
589*7956Sxiuyan.wang@Sun.COM 
590*7956Sxiuyan.wang@Sun.COM 	cmd_buf = &adapter->cmd_buf_arr[0];
591*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < allocated; i++) {
592*7956Sxiuyan.wang@Sun.COM 		dma_p = &cmd_buf->dma_area;
593*7956Sxiuyan.wang@Sun.COM 		unm_free_dma_mem(dma_p);
594*7956Sxiuyan.wang@Sun.COM 		cmd_buf++;
595*7956Sxiuyan.wang@Sun.COM 	}
596*7956Sxiuyan.wang@Sun.COM 	cmn_err(CE_WARN, "%s%d: Failed transmit ring memory allocation\n",
597*7956Sxiuyan.wang@Sun.COM 	    adapter->name, adapter->instance);
598*7956Sxiuyan.wang@Sun.COM 	return (DDI_FAILURE);
599*7956Sxiuyan.wang@Sun.COM }
600*7956Sxiuyan.wang@Sun.COM 
601*7956Sxiuyan.wang@Sun.COM /*
602*7956Sxiuyan.wang@Sun.COM  * Called by freemsg() to "free" the resource.
603*7956Sxiuyan.wang@Sun.COM  */
604*7956Sxiuyan.wang@Sun.COM static void
605*7956Sxiuyan.wang@Sun.COM unm_rx_buffer_recycle(char *arg)
606*7956Sxiuyan.wang@Sun.COM {
607*7956Sxiuyan.wang@Sun.COM 	unm_rx_buffer_t *rx_buffer = (unm_rx_buffer_t *)(uintptr_t)arg;
608*7956Sxiuyan.wang@Sun.COM 	unm_adapter *adapter = rx_buffer->adapter;
609*7956Sxiuyan.wang@Sun.COM 	unm_rcv_desc_ctx_t *rcv_desc = rx_buffer->rcv_desc;
610*7956Sxiuyan.wang@Sun.COM 
611*7956Sxiuyan.wang@Sun.COM 	rx_buffer->mp = desballoc(rx_buffer->dma_info.vaddr,
612*7956Sxiuyan.wang@Sun.COM 	    rcv_desc->dma_size, 0, &rx_buffer->rx_recycle);
613*7956Sxiuyan.wang@Sun.COM 
614*7956Sxiuyan.wang@Sun.COM 	if (rx_buffer->mp == NULL)
615*7956Sxiuyan.wang@Sun.COM 		adapter->stats.desballocfailed++;
616*7956Sxiuyan.wang@Sun.COM 
617*7956Sxiuyan.wang@Sun.COM 	mutex_enter(rcv_desc->recycle_lock);
618*7956Sxiuyan.wang@Sun.COM 	rx_buffer->next = rcv_desc->recycle_list;
619*7956Sxiuyan.wang@Sun.COM 	rcv_desc->recycle_list = rx_buffer;
620*7956Sxiuyan.wang@Sun.COM 	rcv_desc->rx_buf_recycle++;
621*7956Sxiuyan.wang@Sun.COM 	mutex_exit(rcv_desc->recycle_lock);
622*7956Sxiuyan.wang@Sun.COM }
623*7956Sxiuyan.wang@Sun.COM 
624*7956Sxiuyan.wang@Sun.COM void
625*7956Sxiuyan.wang@Sun.COM unm_destroy_rx_ring(unm_rcv_desc_ctx_t *rcv_desc)
626*7956Sxiuyan.wang@Sun.COM {
627*7956Sxiuyan.wang@Sun.COM 	uint32_t i, total_buf;
628*7956Sxiuyan.wang@Sun.COM 	unm_rx_buffer_t *buf_pool;
629*7956Sxiuyan.wang@Sun.COM 
630*7956Sxiuyan.wang@Sun.COM 	total_buf = rcv_desc->rx_buf_total;
631*7956Sxiuyan.wang@Sun.COM 	buf_pool = rcv_desc->rx_buf_pool;
632*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < total_buf; i++) {
633*7956Sxiuyan.wang@Sun.COM 		if (buf_pool->mp != NULL)
634*7956Sxiuyan.wang@Sun.COM 			freemsg(buf_pool->mp);
635*7956Sxiuyan.wang@Sun.COM 		unm_free_dma_mem(&buf_pool->dma_info);
636*7956Sxiuyan.wang@Sun.COM 		buf_pool++;
637*7956Sxiuyan.wang@Sun.COM 	}
638*7956Sxiuyan.wang@Sun.COM 
639*7956Sxiuyan.wang@Sun.COM 	kmem_free(rcv_desc->rx_buf_pool, sizeof (unm_rx_buffer_t) * total_buf);
640*7956Sxiuyan.wang@Sun.COM 	rcv_desc->rx_buf_pool = NULL;
641*7956Sxiuyan.wang@Sun.COM 	rcv_desc->pool_list = NULL;
642*7956Sxiuyan.wang@Sun.COM 	rcv_desc->recycle_list = NULL;
643*7956Sxiuyan.wang@Sun.COM 	rcv_desc->rx_buf_free = 0;
644*7956Sxiuyan.wang@Sun.COM 
645*7956Sxiuyan.wang@Sun.COM 	mutex_destroy(rcv_desc->pool_lock);
646*7956Sxiuyan.wang@Sun.COM 	mutex_destroy(rcv_desc->recycle_lock);
647*7956Sxiuyan.wang@Sun.COM }
648*7956Sxiuyan.wang@Sun.COM 
649*7956Sxiuyan.wang@Sun.COM static int
650*7956Sxiuyan.wang@Sun.COM unm_create_rx_ring(unm_adapter *adapter, unm_rcv_desc_ctx_t *rcv_desc)
651*7956Sxiuyan.wang@Sun.COM {
652*7956Sxiuyan.wang@Sun.COM 	int		i, ret, allocate = 0, sreoff;
653*7956Sxiuyan.wang@Sun.COM 	uint32_t	total_buf;
654*7956Sxiuyan.wang@Sun.COM 	dma_area_t	*dma_info;
655*7956Sxiuyan.wang@Sun.COM 	unm_rx_buffer_t	*rx_buffer;
656*7956Sxiuyan.wang@Sun.COM 
657*7956Sxiuyan.wang@Sun.COM 	sreoff = adapter->ahw.cut_through ? 0 : IP_ALIGNMENT_BYTES;
658*7956Sxiuyan.wang@Sun.COM 
659*7956Sxiuyan.wang@Sun.COM 	/* temporarily set the total rx buffers two times of MaxRxDescCount */
660*7956Sxiuyan.wang@Sun.COM 	total_buf = rcv_desc->rx_buf_total = rcv_desc->MaxRxDescCount * 2;
661*7956Sxiuyan.wang@Sun.COM 
662*7956Sxiuyan.wang@Sun.COM 	rcv_desc->rx_buf_pool = kmem_zalloc(sizeof (unm_rx_buffer_t) *
663*7956Sxiuyan.wang@Sun.COM 	    total_buf, KM_SLEEP);
664*7956Sxiuyan.wang@Sun.COM 	rx_buffer = rcv_desc->rx_buf_pool;
665*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < total_buf; i++) {
666*7956Sxiuyan.wang@Sun.COM 		dma_info = &rx_buffer->dma_info;
667*7956Sxiuyan.wang@Sun.COM 		ret = unm_alloc_dma_mem(adapter, rcv_desc->buf_size,
668*7956Sxiuyan.wang@Sun.COM 		    DDI_DMA_READ | DDI_DMA_STREAMING,
669*7956Sxiuyan.wang@Sun.COM 		    &unm_dma_attr_rxbuf, dma_info);
670*7956Sxiuyan.wang@Sun.COM 		if (ret != DDI_SUCCESS)
671*7956Sxiuyan.wang@Sun.COM 			goto alloc_mem_failed;
672*7956Sxiuyan.wang@Sun.COM 		else {
673*7956Sxiuyan.wang@Sun.COM 			allocate++;
674*7956Sxiuyan.wang@Sun.COM 			dma_info->vaddr = (void *) ((char *)dma_info->vaddr +
675*7956Sxiuyan.wang@Sun.COM 			    sreoff);
676*7956Sxiuyan.wang@Sun.COM 			dma_info->dma_addr += sreoff;
677*7956Sxiuyan.wang@Sun.COM 			rx_buffer->rx_recycle.free_func =
678*7956Sxiuyan.wang@Sun.COM 			    unm_rx_buffer_recycle;
679*7956Sxiuyan.wang@Sun.COM 			rx_buffer->rx_recycle.free_arg = (caddr_t)rx_buffer;
680*7956Sxiuyan.wang@Sun.COM 			rx_buffer->next = NULL;
681*7956Sxiuyan.wang@Sun.COM 			rx_buffer->mp = desballoc(dma_info->vaddr,
682*7956Sxiuyan.wang@Sun.COM 			    rcv_desc->dma_size, 0, &rx_buffer->rx_recycle);
683*7956Sxiuyan.wang@Sun.COM 			if (rx_buffer->mp == NULL)
684*7956Sxiuyan.wang@Sun.COM 				adapter->stats.desballocfailed++;
685*7956Sxiuyan.wang@Sun.COM 			rx_buffer->rcv_desc = rcv_desc;
686*7956Sxiuyan.wang@Sun.COM 			rx_buffer->adapter = adapter;
687*7956Sxiuyan.wang@Sun.COM 			rx_buffer++;
688*7956Sxiuyan.wang@Sun.COM 		}
689*7956Sxiuyan.wang@Sun.COM 	}
690*7956Sxiuyan.wang@Sun.COM 
691*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < (total_buf - 1); i++) {
692*7956Sxiuyan.wang@Sun.COM 		rcv_desc->rx_buf_pool[i].next = &rcv_desc->rx_buf_pool[i + 1];
693*7956Sxiuyan.wang@Sun.COM 	}
694*7956Sxiuyan.wang@Sun.COM 
695*7956Sxiuyan.wang@Sun.COM 	rcv_desc->pool_list = rcv_desc->rx_buf_pool;
696*7956Sxiuyan.wang@Sun.COM 	rcv_desc->recycle_list = NULL;
697*7956Sxiuyan.wang@Sun.COM 	rcv_desc->rx_buf_free = total_buf;
698*7956Sxiuyan.wang@Sun.COM 
699*7956Sxiuyan.wang@Sun.COM 	mutex_init(rcv_desc->pool_lock, NULL,
700*7956Sxiuyan.wang@Sun.COM 	    MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
701*7956Sxiuyan.wang@Sun.COM 	mutex_init(rcv_desc->recycle_lock, NULL,
702*7956Sxiuyan.wang@Sun.COM 	    MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
703*7956Sxiuyan.wang@Sun.COM 
704*7956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
705*7956Sxiuyan.wang@Sun.COM 
706*7956Sxiuyan.wang@Sun.COM alloc_mem_failed:
707*7956Sxiuyan.wang@Sun.COM 	rx_buffer = rcv_desc->rx_buf_pool;
708*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < allocate; i++, rx_buffer++) {
709*7956Sxiuyan.wang@Sun.COM 		dma_info = &rx_buffer->dma_info;
710*7956Sxiuyan.wang@Sun.COM 		if (rx_buffer->mp != NULL)
711*7956Sxiuyan.wang@Sun.COM 			freemsg(rx_buffer->mp);
712*7956Sxiuyan.wang@Sun.COM 		unm_free_dma_mem(dma_info);
713*7956Sxiuyan.wang@Sun.COM 	}
714*7956Sxiuyan.wang@Sun.COM 
715*7956Sxiuyan.wang@Sun.COM 	kmem_free(rcv_desc->rx_buf_pool, sizeof (unm_rx_buffer_t) * total_buf);
716*7956Sxiuyan.wang@Sun.COM 	rcv_desc->rx_buf_pool = NULL;
717*7956Sxiuyan.wang@Sun.COM 
718*7956Sxiuyan.wang@Sun.COM 	cmn_err(CE_WARN, "%s%d: Failed receive ring resource allocation\n",
719*7956Sxiuyan.wang@Sun.COM 	    adapter->name, adapter->instance);
720*7956Sxiuyan.wang@Sun.COM 	return (DDI_FAILURE);
721*7956Sxiuyan.wang@Sun.COM }
722*7956Sxiuyan.wang@Sun.COM 
723*7956Sxiuyan.wang@Sun.COM static void
724*7956Sxiuyan.wang@Sun.COM unm_check_options(unm_adapter *adapter)
725*7956Sxiuyan.wang@Sun.COM {
726*7956Sxiuyan.wang@Sun.COM 	int			i, ring, tx_desc, rx_desc, rx_jdesc;
727*7956Sxiuyan.wang@Sun.COM 	unm_recv_context_t	*recv_ctx;
728*7956Sxiuyan.wang@Sun.COM 	unm_rcv_desc_ctx_t	*rcv_desc;
729*7956Sxiuyan.wang@Sun.COM 	uint8_t			revid = adapter->ahw.revision_id;
730*7956Sxiuyan.wang@Sun.COM 	dev_info_t		*dip = adapter->dip;
731*7956Sxiuyan.wang@Sun.COM 
732*7956Sxiuyan.wang@Sun.COM 	verbmsg = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
733*7956Sxiuyan.wang@Sun.COM 	    dmesg_propname, 0);
734*7956Sxiuyan.wang@Sun.COM 
735*7956Sxiuyan.wang@Sun.COM 	adapter->tx_bcopy_threshold = ddi_prop_get_int(DDI_DEV_T_ANY,
736*7956Sxiuyan.wang@Sun.COM 	    dip, DDI_PROP_DONTPASS, txbcopythreshold_propname,
737*7956Sxiuyan.wang@Sun.COM 	    UNM_TX_BCOPY_THRESHOLD);
738*7956Sxiuyan.wang@Sun.COM 	adapter->rx_bcopy_threshold = ddi_prop_get_int(DDI_DEV_T_ANY,
739*7956Sxiuyan.wang@Sun.COM 	    dip, DDI_PROP_DONTPASS, rxbcopythreshold_propname,
740*7956Sxiuyan.wang@Sun.COM 	    UNM_RX_BCOPY_THRESHOLD);
741*7956Sxiuyan.wang@Sun.COM 
742*7956Sxiuyan.wang@Sun.COM 	tx_desc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
743*7956Sxiuyan.wang@Sun.COM 	    txringsize_propname, MAX_CMD_DESCRIPTORS_HOST);
744*7956Sxiuyan.wang@Sun.COM 	if (tx_desc >= 256 && tx_desc <= MAX_CMD_DESCRIPTORS &&
745*7956Sxiuyan.wang@Sun.COM 	    !(tx_desc & (tx_desc - 1))) {
746*7956Sxiuyan.wang@Sun.COM 		adapter->MaxTxDescCount = tx_desc;
747*7956Sxiuyan.wang@Sun.COM 	} else {
748*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: TxRingSize defaulting to %d, since "
749*7956Sxiuyan.wang@Sun.COM 		    ".conf value is not 2 power aligned in range 256 - %d\n",
750*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance, MAX_CMD_DESCRIPTORS_HOST,
751*7956Sxiuyan.wang@Sun.COM 		    MAX_CMD_DESCRIPTORS);
752*7956Sxiuyan.wang@Sun.COM 		adapter->MaxTxDescCount = MAX_CMD_DESCRIPTORS_HOST;
753*7956Sxiuyan.wang@Sun.COM 	}
754*7956Sxiuyan.wang@Sun.COM 
755*7956Sxiuyan.wang@Sun.COM 	rx_desc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
756*7956Sxiuyan.wang@Sun.COM 	    rxringsize_propname, MAX_RCV_DESCRIPTORS);
757*7956Sxiuyan.wang@Sun.COM 	if (rx_desc >= NX_MIN_DRIVER_RDS_SIZE &&
758*7956Sxiuyan.wang@Sun.COM 	    rx_desc <= NX_MAX_SUPPORTED_RDS_SIZE &&
759*7956Sxiuyan.wang@Sun.COM 	    !(rx_desc & (rx_desc - 1))) {
760*7956Sxiuyan.wang@Sun.COM 		adapter->MaxRxDescCount = rx_desc;
761*7956Sxiuyan.wang@Sun.COM 	} else {
762*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: RxRingSize defaulting to %d, since "
763*7956Sxiuyan.wang@Sun.COM 		    ".conf value is not 2 power aligned in range %d - %d\n",
764*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance, MAX_RCV_DESCRIPTORS,
765*7956Sxiuyan.wang@Sun.COM 		    NX_MIN_DRIVER_RDS_SIZE, NX_MAX_SUPPORTED_RDS_SIZE);
766*7956Sxiuyan.wang@Sun.COM 		adapter->MaxRxDescCount = MAX_RCV_DESCRIPTORS;
767*7956Sxiuyan.wang@Sun.COM 	}
768*7956Sxiuyan.wang@Sun.COM 
769*7956Sxiuyan.wang@Sun.COM 	rx_jdesc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
770*7956Sxiuyan.wang@Sun.COM 	    jumborxringsize_propname, MAX_JUMBO_RCV_DESCRIPTORS);
771*7956Sxiuyan.wang@Sun.COM 	if (rx_jdesc >= NX_MIN_DRIVER_RDS_SIZE &&
772*7956Sxiuyan.wang@Sun.COM 	    rx_jdesc <= NX_MAX_SUPPORTED_JUMBO_RDS_SIZE &&
773*7956Sxiuyan.wang@Sun.COM 	    !(rx_jdesc & (rx_jdesc - 1))) {
774*7956Sxiuyan.wang@Sun.COM 		adapter->MaxJumboRxDescCount = rx_jdesc;
775*7956Sxiuyan.wang@Sun.COM 	} else {
776*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: JumboRingSize defaulting to %d, since "
777*7956Sxiuyan.wang@Sun.COM 		    ".conf value is not 2 power aligned in range %d - %d\n",
778*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance, MAX_JUMBO_RCV_DESCRIPTORS,
779*7956Sxiuyan.wang@Sun.COM 		    NX_MIN_DRIVER_RDS_SIZE, NX_MAX_SUPPORTED_JUMBO_RDS_SIZE);
780*7956Sxiuyan.wang@Sun.COM 		adapter->MaxJumboRxDescCount = MAX_JUMBO_RCV_DESCRIPTORS;
781*7956Sxiuyan.wang@Sun.COM 	}
782*7956Sxiuyan.wang@Sun.COM 
783*7956Sxiuyan.wang@Sun.COM 	adapter->MaxLroRxDescCount = MAX_LRO_RCV_DESCRIPTORS;
784*7956Sxiuyan.wang@Sun.COM 
785*7956Sxiuyan.wang@Sun.COM 	adapter->mtu = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
786*7956Sxiuyan.wang@Sun.COM 	    DDI_PROP_DONTPASS, defaultmtu_propname, MTU_SIZE);
787*7956Sxiuyan.wang@Sun.COM 
788*7956Sxiuyan.wang@Sun.COM 	if (adapter->mtu < MTU_SIZE) {
789*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "Raising mtu to %d\n", MTU_SIZE);
790*7956Sxiuyan.wang@Sun.COM 		adapter->mtu = MTU_SIZE;
791*7956Sxiuyan.wang@Sun.COM 	}
792*7956Sxiuyan.wang@Sun.COM 	adapter->maxmtu = NX_IS_REVISION_P2(revid) ? P2_MAX_MTU : P3_MAX_MTU;
793*7956Sxiuyan.wang@Sun.COM 	if (adapter->mtu > adapter->maxmtu) {
794*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "Lowering mtu to %d\n", adapter->maxmtu);
795*7956Sxiuyan.wang@Sun.COM 		adapter->mtu = adapter->maxmtu;
796*7956Sxiuyan.wang@Sun.COM 	}
797*7956Sxiuyan.wang@Sun.COM 
798*7956Sxiuyan.wang@Sun.COM 	adapter->maxmtu += NX_MAX_ETHERHDR;
799*7956Sxiuyan.wang@Sun.COM 
800*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < MAX_RCV_CTX; ++i) {
801*7956Sxiuyan.wang@Sun.COM 		recv_ctx = &adapter->recv_ctx[i];
802*7956Sxiuyan.wang@Sun.COM 
803*7956Sxiuyan.wang@Sun.COM 		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
804*7956Sxiuyan.wang@Sun.COM 			rcv_desc = &recv_ctx->rcv_desc[ring];
805*7956Sxiuyan.wang@Sun.COM 
806*7956Sxiuyan.wang@Sun.COM 			switch (RCV_DESC_TYPE(ring)) {
807*7956Sxiuyan.wang@Sun.COM 			case RCV_DESC_NORMAL:
808*7956Sxiuyan.wang@Sun.COM 				rcv_desc->MaxRxDescCount =
809*7956Sxiuyan.wang@Sun.COM 				    adapter->MaxRxDescCount;
810*7956Sxiuyan.wang@Sun.COM 				if (adapter->ahw.cut_through) {
811*7956Sxiuyan.wang@Sun.COM 					rcv_desc->dma_size =
812*7956Sxiuyan.wang@Sun.COM 					    NX_CT_DEFAULT_RX_BUF_LEN;
813*7956Sxiuyan.wang@Sun.COM 					rcv_desc->buf_size = rcv_desc->dma_size;
814*7956Sxiuyan.wang@Sun.COM 				} else {
815*7956Sxiuyan.wang@Sun.COM 					rcv_desc->dma_size =
816*7956Sxiuyan.wang@Sun.COM 					    NX_RX_NORMAL_BUF_MAX_LEN;
817*7956Sxiuyan.wang@Sun.COM 					rcv_desc->buf_size =
818*7956Sxiuyan.wang@Sun.COM 					    rcv_desc->dma_size +
819*7956Sxiuyan.wang@Sun.COM 					    IP_ALIGNMENT_BYTES;
820*7956Sxiuyan.wang@Sun.COM 				}
821*7956Sxiuyan.wang@Sun.COM 				break;
822*7956Sxiuyan.wang@Sun.COM 
823*7956Sxiuyan.wang@Sun.COM 			case RCV_DESC_JUMBO:
824*7956Sxiuyan.wang@Sun.COM 				rcv_desc->MaxRxDescCount =
825*7956Sxiuyan.wang@Sun.COM 				    adapter->MaxJumboRxDescCount;
826*7956Sxiuyan.wang@Sun.COM 				if (adapter->ahw.cut_through) {
827*7956Sxiuyan.wang@Sun.COM 					rcv_desc->dma_size =
828*7956Sxiuyan.wang@Sun.COM 					    rcv_desc->buf_size =
829*7956Sxiuyan.wang@Sun.COM 					    NX_P3_RX_JUMBO_BUF_MAX_LEN;
830*7956Sxiuyan.wang@Sun.COM 				} else {
831*7956Sxiuyan.wang@Sun.COM 					if (NX_IS_REVISION_P2(revid))
832*7956Sxiuyan.wang@Sun.COM 						rcv_desc->dma_size =
833*7956Sxiuyan.wang@Sun.COM 						    NX_P2_RX_JUMBO_BUF_MAX_LEN;
834*7956Sxiuyan.wang@Sun.COM 					else
835*7956Sxiuyan.wang@Sun.COM 						rcv_desc->dma_size =
836*7956Sxiuyan.wang@Sun.COM 						    NX_P3_RX_JUMBO_BUF_MAX_LEN;
837*7956Sxiuyan.wang@Sun.COM 					rcv_desc->buf_size =
838*7956Sxiuyan.wang@Sun.COM 					    rcv_desc->dma_size +
839*7956Sxiuyan.wang@Sun.COM 					    IP_ALIGNMENT_BYTES;
840*7956Sxiuyan.wang@Sun.COM 				}
841*7956Sxiuyan.wang@Sun.COM 				break;
842*7956Sxiuyan.wang@Sun.COM 
843*7956Sxiuyan.wang@Sun.COM 			case RCV_RING_LRO:
844*7956Sxiuyan.wang@Sun.COM 				rcv_desc->MaxRxDescCount =
845*7956Sxiuyan.wang@Sun.COM 				    adapter->MaxLroRxDescCount;
846*7956Sxiuyan.wang@Sun.COM 				rcv_desc->buf_size = MAX_RX_LRO_BUFFER_LENGTH;
847*7956Sxiuyan.wang@Sun.COM 				rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN;
848*7956Sxiuyan.wang@Sun.COM 				break;
849*7956Sxiuyan.wang@Sun.COM 			default:
850*7956Sxiuyan.wang@Sun.COM 				break;
851*7956Sxiuyan.wang@Sun.COM 			}
852*7956Sxiuyan.wang@Sun.COM 		}
853*7956Sxiuyan.wang@Sun.COM 	}
854*7956Sxiuyan.wang@Sun.COM }
855*7956Sxiuyan.wang@Sun.COM 
856*7956Sxiuyan.wang@Sun.COM static void
857*7956Sxiuyan.wang@Sun.COM vector128M(unm_adapter *aptr)
858*7956Sxiuyan.wang@Sun.COM {
859*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_change_crbwindow = &unm_nic_pci_change_crbwindow_128M;
860*7956Sxiuyan.wang@Sun.COM 	aptr->unm_crb_writelit_adapter = &unm_crb_writelit_adapter_128M;
861*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_hw_write_wx = &unm_nic_hw_write_wx_128M;
862*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_hw_read_wx = &unm_nic_hw_read_wx_128M;
863*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_hw_write_ioctl = &unm_nic_hw_write_ioctl_128M;
864*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_hw_read_ioctl = &unm_nic_hw_read_ioctl_128M;
865*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_mem_write = &unm_nic_pci_mem_write_128M;
866*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_mem_read = &unm_nic_pci_mem_read_128M;
867*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_write_immediate = &unm_nic_pci_write_immediate_128M;
868*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_read_immediate = &unm_nic_pci_read_immediate_128M;
869*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_write_normalize = &unm_nic_pci_write_normalize_128M;
870*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_read_normalize = &unm_nic_pci_read_normalize_128M;
871*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_set_window = &unm_nic_pci_set_window_128M;
872*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_clear_statistics = &unm_nic_clear_statistics_128M;
873*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_fill_statistics = &unm_nic_fill_statistics_128M;
874*7956Sxiuyan.wang@Sun.COM }
875*7956Sxiuyan.wang@Sun.COM 
876*7956Sxiuyan.wang@Sun.COM static void
877*7956Sxiuyan.wang@Sun.COM vector2M(unm_adapter *aptr)
878*7956Sxiuyan.wang@Sun.COM {
879*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_change_crbwindow = &unm_nic_pci_change_crbwindow_2M;
880*7956Sxiuyan.wang@Sun.COM 	aptr->unm_crb_writelit_adapter = &unm_crb_writelit_adapter_2M;
881*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_hw_write_wx = &unm_nic_hw_write_wx_2M;
882*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_hw_read_wx = &unm_nic_hw_read_wx_2M;
883*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_hw_write_ioctl = &unm_nic_hw_write_wx_2M;
884*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_hw_read_ioctl = &unm_nic_hw_read_wx_2M;
885*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_mem_write = &unm_nic_pci_mem_write_2M;
886*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_mem_read = &unm_nic_pci_mem_read_2M;
887*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_write_immediate = &unm_nic_pci_write_immediate_2M;
888*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_read_immediate = &unm_nic_pci_read_immediate_2M;
889*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_write_normalize = &unm_nic_pci_write_normalize_2M;
890*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_read_normalize = &unm_nic_pci_read_normalize_2M;
891*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_pci_set_window = &unm_nic_pci_set_window_2M;
892*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_clear_statistics = &unm_nic_clear_statistics_2M;
893*7956Sxiuyan.wang@Sun.COM 	aptr->unm_nic_fill_statistics = &unm_nic_fill_statistics_2M;
894*7956Sxiuyan.wang@Sun.COM }
895*7956Sxiuyan.wang@Sun.COM 
896*7956Sxiuyan.wang@Sun.COM static int
897*7956Sxiuyan.wang@Sun.COM unm_pci_map_setup(unm_adapter *adapter)
898*7956Sxiuyan.wang@Sun.COM {
899*7956Sxiuyan.wang@Sun.COM 	int ret;
900*7956Sxiuyan.wang@Sun.COM 	caddr_t reg_base, db_base;
901*7956Sxiuyan.wang@Sun.COM 	caddr_t mem_ptr0, mem_ptr1 = NULL, mem_ptr2 = NULL;
902*7956Sxiuyan.wang@Sun.COM 	unsigned long pci_len0;
903*7956Sxiuyan.wang@Sun.COM 	unsigned long first_page_group_start, first_page_group_end;
904*7956Sxiuyan.wang@Sun.COM 
905*7956Sxiuyan.wang@Sun.COM 	off_t regsize, dbsize = UNM_DB_MAPSIZE_BYTES;
906*7956Sxiuyan.wang@Sun.COM 	dev_info_t *dip = adapter->dip;
907*7956Sxiuyan.wang@Sun.COM 
908*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.qdr_sn_window = adapter->ahw.ddr_mn_window = -1;
909*7956Sxiuyan.wang@Sun.COM 
910*7956Sxiuyan.wang@Sun.COM 	/* map register space */
911*7956Sxiuyan.wang@Sun.COM 
912*7956Sxiuyan.wang@Sun.COM 	ret = ddi_dev_regsize(dip, 1, &regsize);
913*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
914*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: failed to read reg size for bar0\n",
915*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
916*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
917*7956Sxiuyan.wang@Sun.COM 	}
918*7956Sxiuyan.wang@Sun.COM 
919*7956Sxiuyan.wang@Sun.COM 	ret = ddi_regs_map_setup(dip, 1, &reg_base, 0,
920*7956Sxiuyan.wang@Sun.COM 	    regsize, &unm_dev_attr, &adapter->regs_handle);
921*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
922*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: failed to map registers\n",
923*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
924*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
925*7956Sxiuyan.wang@Sun.COM 	}
926*7956Sxiuyan.wang@Sun.COM 
927*7956Sxiuyan.wang@Sun.COM 	mem_ptr0 = reg_base;
928*7956Sxiuyan.wang@Sun.COM 
929*7956Sxiuyan.wang@Sun.COM 	if (regsize == UNM_PCI_128MB_SIZE) {
930*7956Sxiuyan.wang@Sun.COM 		pci_len0 = FIRST_PAGE_GROUP_SIZE;
931*7956Sxiuyan.wang@Sun.COM 		mem_ptr1 = mem_ptr0 + SECOND_PAGE_GROUP_START;
932*7956Sxiuyan.wang@Sun.COM 		mem_ptr2 = mem_ptr0 + THIRD_PAGE_GROUP_START;
933*7956Sxiuyan.wang@Sun.COM 		first_page_group_start = FIRST_PAGE_GROUP_START;
934*7956Sxiuyan.wang@Sun.COM 		first_page_group_end   = FIRST_PAGE_GROUP_END;
935*7956Sxiuyan.wang@Sun.COM 		vector128M(adapter);
936*7956Sxiuyan.wang@Sun.COM 	} else if (regsize == UNM_PCI_32MB_SIZE) {
937*7956Sxiuyan.wang@Sun.COM 		pci_len0 = 0;
938*7956Sxiuyan.wang@Sun.COM 		mem_ptr1 = mem_ptr0;
939*7956Sxiuyan.wang@Sun.COM 		mem_ptr2 = mem_ptr0 +
940*7956Sxiuyan.wang@Sun.COM 		    (THIRD_PAGE_GROUP_START - SECOND_PAGE_GROUP_START);
941*7956Sxiuyan.wang@Sun.COM 		first_page_group_start = 0;
942*7956Sxiuyan.wang@Sun.COM 		first_page_group_end   = 0;
943*7956Sxiuyan.wang@Sun.COM 		vector128M(adapter);
944*7956Sxiuyan.wang@Sun.COM 	} else if (regsize == UNM_PCI_2MB_SIZE) {
945*7956Sxiuyan.wang@Sun.COM 		pci_len0 = UNM_PCI_2MB_SIZE;
946*7956Sxiuyan.wang@Sun.COM 		first_page_group_start = 0;
947*7956Sxiuyan.wang@Sun.COM 		first_page_group_end = 0;
948*7956Sxiuyan.wang@Sun.COM 		adapter->ahw.ddr_mn_window = adapter->ahw.qdr_sn_window = 0;
949*7956Sxiuyan.wang@Sun.COM 		adapter->ahw.mn_win_crb = 0x100000 + PCIX_MN_WINDOW +
950*7956Sxiuyan.wang@Sun.COM 		    (adapter->ahw.pci_func * 0x20);
951*7956Sxiuyan.wang@Sun.COM 		if (adapter->ahw.pci_func < 4)
952*7956Sxiuyan.wang@Sun.COM 			adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW +
953*7956Sxiuyan.wang@Sun.COM 			    (adapter->ahw.pci_func * 0x20);
954*7956Sxiuyan.wang@Sun.COM 		else
955*7956Sxiuyan.wang@Sun.COM 			adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW +
956*7956Sxiuyan.wang@Sun.COM 			    0xA0 + ((adapter->ahw.pci_func - 4) * 0x10);
957*7956Sxiuyan.wang@Sun.COM 		vector2M(adapter);
958*7956Sxiuyan.wang@Sun.COM 	} else {
959*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: invalid pci regs map size %ld\n",
960*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance, regsize);
961*7956Sxiuyan.wang@Sun.COM 		ddi_regs_map_free(&adapter->regs_handle);
962*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
963*7956Sxiuyan.wang@Sun.COM 	}
964*7956Sxiuyan.wang@Sun.COM 
965*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.pci_base0  = (unsigned long)mem_ptr0;
966*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.pci_len0   = pci_len0;
967*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.pci_base1  = (unsigned long)mem_ptr1;
968*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.pci_len1   = SECOND_PAGE_GROUP_SIZE;
969*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.pci_base2  = (unsigned long)mem_ptr2;
970*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.pci_len2   = THIRD_PAGE_GROUP_SIZE;
971*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.crb_base   =
972*7956Sxiuyan.wang@Sun.COM 	    PCI_OFFSET_SECOND_RANGE(adapter, UNM_PCI_CRBSPACE);
973*7956Sxiuyan.wang@Sun.COM 
974*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.first_page_group_start = first_page_group_start;
975*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.first_page_group_end   = first_page_group_end;
976*7956Sxiuyan.wang@Sun.COM 
977*7956Sxiuyan.wang@Sun.COM 	/* map doorbell */
978*7956Sxiuyan.wang@Sun.COM 
979*7956Sxiuyan.wang@Sun.COM 	ret = ddi_regs_map_setup(dip, 2, &db_base, 0,
980*7956Sxiuyan.wang@Sun.COM 	    dbsize, &unm_dev_attr, &adapter->db_handle);
981*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
982*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: failed to map doorbell\n",
983*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
984*7956Sxiuyan.wang@Sun.COM 		ddi_regs_map_free(&adapter->regs_handle);
985*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
986*7956Sxiuyan.wang@Sun.COM 	}
987*7956Sxiuyan.wang@Sun.COM 
988*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.db_base   = (unsigned long)db_base;
989*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.db_len    = dbsize;
990*7956Sxiuyan.wang@Sun.COM 
991*7956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
992*7956Sxiuyan.wang@Sun.COM }
993*7956Sxiuyan.wang@Sun.COM 
994*7956Sxiuyan.wang@Sun.COM static int
995*7956Sxiuyan.wang@Sun.COM unm_initialize_intr(unm_adapter *adapter)
996*7956Sxiuyan.wang@Sun.COM {
997*7956Sxiuyan.wang@Sun.COM 
998*7956Sxiuyan.wang@Sun.COM 	int		ret;
999*7956Sxiuyan.wang@Sun.COM 	int		type, count, avail, actual;
1000*7956Sxiuyan.wang@Sun.COM 
1001*7956Sxiuyan.wang@Sun.COM 	ret = ddi_intr_get_supported_types(adapter->dip, &type);
1002*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
1003*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: ddi_intr_get_supported_types() "
1004*7956Sxiuyan.wang@Sun.COM 		    "failed\n", adapter->name, adapter->instance);
1005*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
1006*7956Sxiuyan.wang@Sun.COM 	}
1007*7956Sxiuyan.wang@Sun.COM 
1008*7956Sxiuyan.wang@Sun.COM 	type = DDI_INTR_TYPE_MSI;
1009*7956Sxiuyan.wang@Sun.COM 	ret = ddi_intr_get_nintrs(adapter->dip, type, &count);
1010*7956Sxiuyan.wang@Sun.COM 	if ((ret == DDI_SUCCESS) && (count > 0))
1011*7956Sxiuyan.wang@Sun.COM 		goto found_msi;
1012*7956Sxiuyan.wang@Sun.COM 
1013*7956Sxiuyan.wang@Sun.COM 	type = DDI_INTR_TYPE_FIXED;
1014*7956Sxiuyan.wang@Sun.COM 	ret = ddi_intr_get_nintrs(adapter->dip, type, &count);
1015*7956Sxiuyan.wang@Sun.COM 	if ((ret != DDI_SUCCESS) || (count == 0)) {
1016*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN,
1017*7956Sxiuyan.wang@Sun.COM 		    "ddi_intr_get_nintrs() failure ret=%d\n", ret);
1018*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
1019*7956Sxiuyan.wang@Sun.COM 	}
1020*7956Sxiuyan.wang@Sun.COM 
1021*7956Sxiuyan.wang@Sun.COM found_msi:
1022*7956Sxiuyan.wang@Sun.COM 	adapter->intr_type = type;
1023*7956Sxiuyan.wang@Sun.COM 	adapter->flags &= ~(UNM_NIC_MSI_ENABLED | UNM_NIC_MSIX_ENABLED);
1024*7956Sxiuyan.wang@Sun.COM 	if (type == DDI_INTR_TYPE_MSI)
1025*7956Sxiuyan.wang@Sun.COM 		adapter->flags |= UNM_NIC_MSI_ENABLED;
1026*7956Sxiuyan.wang@Sun.COM 
1027*7956Sxiuyan.wang@Sun.COM 	/* Get number of available interrupts */
1028*7956Sxiuyan.wang@Sun.COM 	ret = ddi_intr_get_navail(adapter->dip, type, &avail);
1029*7956Sxiuyan.wang@Sun.COM 	if ((ret != DDI_SUCCESS) || (avail == 0)) {
1030*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "ddi_intr_get_navail() failure, ret=%d\n",
1031*7956Sxiuyan.wang@Sun.COM 		    ret);
1032*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
1033*7956Sxiuyan.wang@Sun.COM 	}
1034*7956Sxiuyan.wang@Sun.COM 
1035*7956Sxiuyan.wang@Sun.COM 	ret = ddi_intr_alloc(adapter->dip, &adapter->intr_handle,
1036*7956Sxiuyan.wang@Sun.COM 	    type, 0, 1, &actual, DDI_INTR_ALLOC_NORMAL);
1037*7956Sxiuyan.wang@Sun.COM 	if ((ret != DDI_SUCCESS) || (actual == 0)) {
1038*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "ddi_intr_alloc() failure: %d\n", ret);
1039*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
1040*7956Sxiuyan.wang@Sun.COM 	}
1041*7956Sxiuyan.wang@Sun.COM 
1042*7956Sxiuyan.wang@Sun.COM 	ret = ddi_intr_get_pri(adapter->intr_handle, &adapter->intr_pri);
1043*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
1044*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "ddi_intr_get_pri() failure: %d\n", ret);
1045*7956Sxiuyan.wang@Sun.COM 	}
1046*7956Sxiuyan.wang@Sun.COM 
1047*7956Sxiuyan.wang@Sun.COM 	/* Call ddi_intr_add_handler() */
1048*7956Sxiuyan.wang@Sun.COM 	ret = ddi_intr_add_handler(adapter->intr_handle, unm_intr,
1049*7956Sxiuyan.wang@Sun.COM 	    (caddr_t)adapter, NULL);
1050*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
1051*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: ddi_intr_add_handler() failure\n",
1052*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
1053*7956Sxiuyan.wang@Sun.COM 		(void) ddi_intr_free(adapter->intr_handle);
1054*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
1055*7956Sxiuyan.wang@Sun.COM 	}
1056*7956Sxiuyan.wang@Sun.COM 
1057*7956Sxiuyan.wang@Sun.COM 	/* Add softintr if required */
1058*7956Sxiuyan.wang@Sun.COM 
1059*7956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
1060*7956Sxiuyan.wang@Sun.COM 
1061*7956Sxiuyan.wang@Sun.COM }
1062*7956Sxiuyan.wang@Sun.COM 
1063*7956Sxiuyan.wang@Sun.COM void
1064*7956Sxiuyan.wang@Sun.COM unm_destroy_intr(unm_adapter *adapter)
1065*7956Sxiuyan.wang@Sun.COM {
1066*7956Sxiuyan.wang@Sun.COM 	/* disable interrupt */
1067*7956Sxiuyan.wang@Sun.COM 	if (adapter->intr_type == DDI_INTR_TYPE_MSI)
1068*7956Sxiuyan.wang@Sun.COM 		(void) ddi_intr_block_disable(&adapter->intr_handle, 1);
1069*7956Sxiuyan.wang@Sun.COM 	else
1070*7956Sxiuyan.wang@Sun.COM 		(void) ddi_intr_disable(adapter->intr_handle);
1071*7956Sxiuyan.wang@Sun.COM 
1072*7956Sxiuyan.wang@Sun.COM 	(void) ddi_intr_remove_handler(adapter->intr_handle);
1073*7956Sxiuyan.wang@Sun.COM 	(void) ddi_intr_free(adapter->intr_handle);
1074*7956Sxiuyan.wang@Sun.COM 
1075*7956Sxiuyan.wang@Sun.COM 	/* Remove the software intr handler */
1076*7956Sxiuyan.wang@Sun.COM }
1077*7956Sxiuyan.wang@Sun.COM 
1078*7956Sxiuyan.wang@Sun.COM static void
1079*7956Sxiuyan.wang@Sun.COM netxen_set_port_mode(unm_adapter *adapter)
1080*7956Sxiuyan.wang@Sun.COM {
1081*7956Sxiuyan.wang@Sun.COM 	static int	wol_port_mode = UNM_PORT_MODE_AUTO_NEG_1G;
1082*7956Sxiuyan.wang@Sun.COM 	static int	port_mode = UNM_PORT_MODE_AUTO_NEG;
1083*7956Sxiuyan.wang@Sun.COM 	int		btype = adapter->ahw.boardcfg.board_type, data = 0;
1084*7956Sxiuyan.wang@Sun.COM 
1085*7956Sxiuyan.wang@Sun.COM 	if (btype == UNM_BRDTYPE_P3_HMEZ || btype == UNM_BRDTYPE_P3_XG_LOM) {
1086*7956Sxiuyan.wang@Sun.COM 		data = port_mode;	/* set to port_mode normally */
1087*7956Sxiuyan.wang@Sun.COM 		if ((port_mode != UNM_PORT_MODE_802_3_AP) &&
1088*7956Sxiuyan.wang@Sun.COM 		    (port_mode != UNM_PORT_MODE_XG) &&
1089*7956Sxiuyan.wang@Sun.COM 		    (port_mode != UNM_PORT_MODE_AUTO_NEG_1G) &&
1090*7956Sxiuyan.wang@Sun.COM 		    (port_mode != UNM_PORT_MODE_AUTO_NEG_XG))
1091*7956Sxiuyan.wang@Sun.COM 			data = UNM_PORT_MODE_AUTO_NEG;
1092*7956Sxiuyan.wang@Sun.COM 
1093*7956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, UNM_PORT_MODE_ADDR,
1094*7956Sxiuyan.wang@Sun.COM 		    &data, 4);
1095*7956Sxiuyan.wang@Sun.COM 
1096*7956Sxiuyan.wang@Sun.COM 		if ((wol_port_mode != UNM_PORT_MODE_802_3_AP) &&
1097*7956Sxiuyan.wang@Sun.COM 		    (wol_port_mode != UNM_PORT_MODE_XG) &&
1098*7956Sxiuyan.wang@Sun.COM 		    (wol_port_mode != UNM_PORT_MODE_AUTO_NEG_1G) &&
1099*7956Sxiuyan.wang@Sun.COM 		    (wol_port_mode != UNM_PORT_MODE_AUTO_NEG_XG))
1100*7956Sxiuyan.wang@Sun.COM 			wol_port_mode = UNM_PORT_MODE_AUTO_NEG;
1101*7956Sxiuyan.wang@Sun.COM 
1102*7956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, UNM_WOL_PORT_MODE,
1103*7956Sxiuyan.wang@Sun.COM 		    &wol_port_mode, 4);
1104*7956Sxiuyan.wang@Sun.COM 	}
1105*7956Sxiuyan.wang@Sun.COM }
1106*7956Sxiuyan.wang@Sun.COM 
1107*7956Sxiuyan.wang@Sun.COM static void
1108*7956Sxiuyan.wang@Sun.COM netxen_pcie_strap_init(unm_adapter *adapter)
1109*7956Sxiuyan.wang@Sun.COM {
1110*7956Sxiuyan.wang@Sun.COM 	ddi_acc_handle_t	pcihdl = adapter->pci_cfg_handle;
1111*7956Sxiuyan.wang@Sun.COM 	u32			chicken, control, c8c9value = 0xF1000;
1112*7956Sxiuyan.wang@Sun.COM 
1113*7956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_read_wx(adapter, UNM_PCIE_REG(PCIE_CHICKEN3),
1114*7956Sxiuyan.wang@Sun.COM 	    &chicken, 4);
1115*7956Sxiuyan.wang@Sun.COM 
1116*7956Sxiuyan.wang@Sun.COM 	chicken &= 0xFCFFFFFF;		/* clear chicken3 25:24 */
1117*7956Sxiuyan.wang@Sun.COM 	control = pci_config_get32(pcihdl, 0xD0);
1118*7956Sxiuyan.wang@Sun.COM 	if ((control & 0x000F0000) != 0x00020000)	/* is it gen1? */
1119*7956Sxiuyan.wang@Sun.COM 		chicken |= 0x01000000;
1120*7956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_PCIE_REG(PCIE_CHICKEN3),
1121*7956Sxiuyan.wang@Sun.COM 	    &chicken, 4);
1122*7956Sxiuyan.wang@Sun.COM 	control = pci_config_get32(pcihdl, 0xC8);
1123*7956Sxiuyan.wang@Sun.COM 	control = pci_config_get32(pcihdl, 0xC8);
1124*7956Sxiuyan.wang@Sun.COM 	pci_config_put32(pcihdl, 0xC8, c8c9value);
1125*7956Sxiuyan.wang@Sun.COM }
1126*7956Sxiuyan.wang@Sun.COM 
1127*7956Sxiuyan.wang@Sun.COM static int
1128*7956Sxiuyan.wang@Sun.COM netxen_read_mac_addr(unm_adapter *adapter)
1129*7956Sxiuyan.wang@Sun.COM {
1130*7956Sxiuyan.wang@Sun.COM 	u64		mac_addr[FLASH_NUM_PORTS + 1];
1131*7956Sxiuyan.wang@Sun.COM 	unsigned char	*p;
1132*7956Sxiuyan.wang@Sun.COM 	int		i;
1133*7956Sxiuyan.wang@Sun.COM 
1134*7956Sxiuyan.wang@Sun.COM 	if (is_flash_supported(adapter) != 0)
1135*7956Sxiuyan.wang@Sun.COM 		return (-1);
1136*7956Sxiuyan.wang@Sun.COM 
1137*7956Sxiuyan.wang@Sun.COM 	if (get_flash_mac_addr(adapter, mac_addr) != 0)
1138*7956Sxiuyan.wang@Sun.COM 		return (-1);
1139*7956Sxiuyan.wang@Sun.COM 
1140*7956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
1141*7956Sxiuyan.wang@Sun.COM 		p = (unsigned char *)&mac_addr[adapter->ahw.pci_func];
1142*7956Sxiuyan.wang@Sun.COM 	else
1143*7956Sxiuyan.wang@Sun.COM 		p = (unsigned char *)&mac_addr[adapter->portnum];
1144*7956Sxiuyan.wang@Sun.COM 
1145*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < 6; i++)
1146*7956Sxiuyan.wang@Sun.COM 		adapter->mac_addr[i] = p[5 - i];
1147*7956Sxiuyan.wang@Sun.COM 
1148*7956Sxiuyan.wang@Sun.COM 	if (unm_nic_macaddr_set(adapter, adapter->mac_addr) != 0)
1149*7956Sxiuyan.wang@Sun.COM 		return (-1);
1150*7956Sxiuyan.wang@Sun.COM 
1151*7956Sxiuyan.wang@Sun.COM 	return (0);
1152*7956Sxiuyan.wang@Sun.COM }
1153*7956Sxiuyan.wang@Sun.COM 
1154*7956Sxiuyan.wang@Sun.COM static int
1155*7956Sxiuyan.wang@Sun.COM unmattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1156*7956Sxiuyan.wang@Sun.COM {
1157*7956Sxiuyan.wang@Sun.COM 	unm_adapter			*adapter;
1158*7956Sxiuyan.wang@Sun.COM 	unm_recv_context_t		*recv_ctx = NULL;
1159*7956Sxiuyan.wang@Sun.COM 	unm_rcv_desc_ctx_t		*rcv_desc = NULL;
1160*7956Sxiuyan.wang@Sun.COM 	int				i, first_driver = 0;
1161*7956Sxiuyan.wang@Sun.COM 	int				ret, ring, temp;
1162*7956Sxiuyan.wang@Sun.COM 
1163*7956Sxiuyan.wang@Sun.COM 	switch (cmd) {
1164*7956Sxiuyan.wang@Sun.COM 	case DDI_ATTACH:
1165*7956Sxiuyan.wang@Sun.COM 		break;
1166*7956Sxiuyan.wang@Sun.COM 	case DDI_RESUME:
1167*7956Sxiuyan.wang@Sun.COM 	case DDI_PM_RESUME:
1168*7956Sxiuyan.wang@Sun.COM 	default:
1169*7956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
1170*7956Sxiuyan.wang@Sun.COM 	}
1171*7956Sxiuyan.wang@Sun.COM 
1172*7956Sxiuyan.wang@Sun.COM 	adapter = kmem_zalloc(sizeof (unm_adapter), KM_SLEEP);
1173*7956Sxiuyan.wang@Sun.COM 	adapter->dip = dip;
1174*7956Sxiuyan.wang@Sun.COM 	ddi_set_driver_private(dip, adapter);
1175*7956Sxiuyan.wang@Sun.COM 	adapter->instance = ddi_get_instance(dip);
1176*7956Sxiuyan.wang@Sun.COM 
1177*7956Sxiuyan.wang@Sun.COM 	adapter->name = ddi_driver_name(dip);
1178*7956Sxiuyan.wang@Sun.COM 
1179*7956Sxiuyan.wang@Sun.COM 	ret = pci_config_setup(dip, &adapter->pci_cfg_handle);
1180*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
1181*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: pci_config_setup failed\n",
1182*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
1183*7956Sxiuyan.wang@Sun.COM 		goto attach_setup_err;
1184*7956Sxiuyan.wang@Sun.COM 	}
1185*7956Sxiuyan.wang@Sun.COM 
1186*7956Sxiuyan.wang@Sun.COM 	ret = unm_pci_cfg_init(adapter);
1187*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS)
1188*7956Sxiuyan.wang@Sun.COM 		goto attach_err;
1189*7956Sxiuyan.wang@Sun.COM 
1190*7956Sxiuyan.wang@Sun.COM 	ret = unm_pci_map_setup(adapter);
1191*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS)
1192*7956Sxiuyan.wang@Sun.COM 		goto attach_err;
1193*7956Sxiuyan.wang@Sun.COM 
1194*7956Sxiuyan.wang@Sun.COM 	if (unm_initialize_intr(adapter) != DDI_SUCCESS)
1195*7956Sxiuyan.wang@Sun.COM 		goto attach_unmap_regs;
1196*7956Sxiuyan.wang@Sun.COM 
1197*7956Sxiuyan.wang@Sun.COM 	rw_init(&adapter->adapter_lock, NULL,
1198*7956Sxiuyan.wang@Sun.COM 	    RW_DRIVER, DDI_INTR_PRI(adapter->intr_pri));
1199*7956Sxiuyan.wang@Sun.COM 	mutex_init(&adapter->tx_lock, NULL,
1200*7956Sxiuyan.wang@Sun.COM 	    MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
1201*7956Sxiuyan.wang@Sun.COM 	mutex_init(&adapter->lock, NULL,
1202*7956Sxiuyan.wang@Sun.COM 	    MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
1203*7956Sxiuyan.wang@Sun.COM 
1204*7956Sxiuyan.wang@Sun.COM 	adapter->portnum = (int8_t)adapter->ahw.pci_func;
1205*7956Sxiuyan.wang@Sun.COM 
1206*7956Sxiuyan.wang@Sun.COM 	/*
1207*7956Sxiuyan.wang@Sun.COM 	 * Set the CRB window to invalid. If any register in window 0 is
1208*7956Sxiuyan.wang@Sun.COM 	 * accessed it should set window to 0 and then reset it to 1.
1209*7956Sxiuyan.wang@Sun.COM 	 */
1210*7956Sxiuyan.wang@Sun.COM 	adapter->curr_window = 255;
1211*7956Sxiuyan.wang@Sun.COM 
1212*7956Sxiuyan.wang@Sun.COM 	adapter->fw_major = adapter->unm_nic_pci_read_normalize(adapter,
1213*7956Sxiuyan.wang@Sun.COM 	    UNM_FW_VERSION_MAJOR);
1214*7956Sxiuyan.wang@Sun.COM 
1215*7956Sxiuyan.wang@Sun.COM 	if (adapter->fw_major < 4)
1216*7956Sxiuyan.wang@Sun.COM 		adapter->max_rds_rings = 3;
1217*7956Sxiuyan.wang@Sun.COM 	else
1218*7956Sxiuyan.wang@Sun.COM 		adapter->max_rds_rings = 2;
1219*7956Sxiuyan.wang@Sun.COM 
1220*7956Sxiuyan.wang@Sun.COM 	STRUCT_COPY(adapter->gc_dma_attr_desc, unm_dma_attr_desc);
1221*7956Sxiuyan.wang@Sun.COM 	STRUCT_COPY(adapter->gc_attr_desc, unm_buf_attr);
1222*7956Sxiuyan.wang@Sun.COM 
1223*7956Sxiuyan.wang@Sun.COM 	ret = unm_nic_get_board_info(adapter);
1224*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
1225*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: error reading board config\n",
1226*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
1227*7956Sxiuyan.wang@Sun.COM 		goto attach_destroy_intr;
1228*7956Sxiuyan.wang@Sun.COM 	}
1229*7956Sxiuyan.wang@Sun.COM 
1230*7956Sxiuyan.wang@Sun.COM 	/* Mezz cards have PCI function 0, 2, 3 enabled */
1231*7956Sxiuyan.wang@Sun.COM 	switch (adapter->ahw.boardcfg.board_type) {
1232*7956Sxiuyan.wang@Sun.COM 	case UNM_BRDTYPE_P2_SB31_10G_IMEZ:
1233*7956Sxiuyan.wang@Sun.COM 	case UNM_BRDTYPE_P2_SB31_10G_HMEZ:
1234*7956Sxiuyan.wang@Sun.COM 		if (adapter->ahw.pci_func >= 2) {
1235*7956Sxiuyan.wang@Sun.COM 			adapter->portnum = adapter->ahw.pci_func - 2;
1236*7956Sxiuyan.wang@Sun.COM 		}
1237*7956Sxiuyan.wang@Sun.COM 	default:
1238*7956Sxiuyan.wang@Sun.COM 		break;
1239*7956Sxiuyan.wang@Sun.COM 	}
1240*7956Sxiuyan.wang@Sun.COM 
1241*7956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
1242*7956Sxiuyan.wang@Sun.COM 		temp = UNM_CRB_READ_VAL_ADAPTER(UNM_MIU_MN_CONTROL, adapter);
1243*7956Sxiuyan.wang@Sun.COM 		adapter->ahw.cut_through = NX_IS_SYSTEM_CUT_THROUGH(temp);
1244*7956Sxiuyan.wang@Sun.COM 		if (adapter->ahw.pci_func == 0)
1245*7956Sxiuyan.wang@Sun.COM 			first_driver = 1;
1246*7956Sxiuyan.wang@Sun.COM 	} else {
1247*7956Sxiuyan.wang@Sun.COM 		if (adapter->portnum == 0)
1248*7956Sxiuyan.wang@Sun.COM 			first_driver = 1;
1249*7956Sxiuyan.wang@Sun.COM 	}
1250*7956Sxiuyan.wang@Sun.COM 
1251*7956Sxiuyan.wang@Sun.COM 	unm_check_options(adapter);
1252*7956Sxiuyan.wang@Sun.COM 
1253*7956Sxiuyan.wang@Sun.COM 	if (first_driver) {
1254*7956Sxiuyan.wang@Sun.COM 		int first_boot = adapter->unm_nic_pci_read_normalize(adapter,
1255*7956Sxiuyan.wang@Sun.COM 		    UNM_CAM_RAM(0x1fc));
1256*7956Sxiuyan.wang@Sun.COM 
1257*7956Sxiuyan.wang@Sun.COM 		if (check_hw_init(adapter) != 0) {
1258*7956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "%s%d: Error in HW init sequence\n",
1259*7956Sxiuyan.wang@Sun.COM 			    adapter->name, adapter->instance);
1260*7956Sxiuyan.wang@Sun.COM 			goto attach_destroy_intr;
1261*7956Sxiuyan.wang@Sun.COM 		}
1262*7956Sxiuyan.wang@Sun.COM 
1263*7956Sxiuyan.wang@Sun.COM 		if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
1264*7956Sxiuyan.wang@Sun.COM 			netxen_set_port_mode(adapter);
1265*7956Sxiuyan.wang@Sun.COM 
1266*7956Sxiuyan.wang@Sun.COM 		if (first_boot != 0x55555555) {
1267*7956Sxiuyan.wang@Sun.COM 			temp = 0;
1268*7956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_write_wx(adapter, CRB_CMDPEG_STATE,
1269*7956Sxiuyan.wang@Sun.COM 			    &temp, 4);
1270*7956Sxiuyan.wang@Sun.COM 			if (pinit_from_rom(adapter, 0) != 0)
1271*7956Sxiuyan.wang@Sun.COM 				goto attach_destroy_intr;
1272*7956Sxiuyan.wang@Sun.COM 
1273*7956Sxiuyan.wang@Sun.COM 			drv_usecwait(500);
1274*7956Sxiuyan.wang@Sun.COM 
1275*7956Sxiuyan.wang@Sun.COM 			ret = load_from_flash(adapter);
1276*7956Sxiuyan.wang@Sun.COM 			if (ret != DDI_SUCCESS)
1277*7956Sxiuyan.wang@Sun.COM 				goto attach_destroy_intr;
1278*7956Sxiuyan.wang@Sun.COM 		}
1279*7956Sxiuyan.wang@Sun.COM 
1280*7956Sxiuyan.wang@Sun.COM 		if (ret = unm_initialize_dummy_dma(adapter))
1281*7956Sxiuyan.wang@Sun.COM 			goto attach_destroy_intr;
1282*7956Sxiuyan.wang@Sun.COM 
1283*7956Sxiuyan.wang@Sun.COM 		/*
1284*7956Sxiuyan.wang@Sun.COM 		 * Tell the hardware our version number.
1285*7956Sxiuyan.wang@Sun.COM 		 */
1286*7956Sxiuyan.wang@Sun.COM 		i = (_UNM_NIC_MAJOR << 16) |
1287*7956Sxiuyan.wang@Sun.COM 		    ((_UNM_NIC_MINOR << 8)) | (_UNM_NIC_SUBVERSION);
1288*7956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, CRB_DRIVER_VERSION,
1289*7956Sxiuyan.wang@Sun.COM 		    &i, 4);
1290*7956Sxiuyan.wang@Sun.COM 
1291*7956Sxiuyan.wang@Sun.COM 		/* Unlock the HW, prompting the boot sequence */
1292*7956Sxiuyan.wang@Sun.COM 		if ((first_boot == 0x55555555) &&
1293*7956Sxiuyan.wang@Sun.COM 		    (NX_IS_REVISION_P2(adapter->ahw.revision_id)))
1294*7956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_pci_write_normalize(adapter,
1295*7956Sxiuyan.wang@Sun.COM 			    UNM_ROMUSB_GLB_PEGTUNE_DONE, 1);
1296*7956Sxiuyan.wang@Sun.COM 
1297*7956Sxiuyan.wang@Sun.COM 		/* Handshake with the card before we register the devices. */
1298*7956Sxiuyan.wang@Sun.COM 		if (phantom_init(adapter, 0) != DDI_SUCCESS)
1299*7956Sxiuyan.wang@Sun.COM 			goto attach_destroy_intr;
1300*7956Sxiuyan.wang@Sun.COM 	}
1301*7956Sxiuyan.wang@Sun.COM 
1302*7956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
1303*7956Sxiuyan.wang@Sun.COM 		netxen_pcie_strap_init(adapter);
1304*7956Sxiuyan.wang@Sun.COM 
1305*7956Sxiuyan.wang@Sun.COM 	/*
1306*7956Sxiuyan.wang@Sun.COM 	 * See if the firmware gave us a virtual-physical port mapping.
1307*7956Sxiuyan.wang@Sun.COM 	 */
1308*7956Sxiuyan.wang@Sun.COM 	adapter->physical_port = adapter->portnum;
1309*7956Sxiuyan.wang@Sun.COM 	i = adapter->unm_nic_pci_read_normalize(adapter,
1310*7956Sxiuyan.wang@Sun.COM 	    CRB_V2P(adapter->portnum));
1311*7956Sxiuyan.wang@Sun.COM 	if (i != 0x55555555)
1312*7956Sxiuyan.wang@Sun.COM 		adapter->physical_port = (uint16_t)i;
1313*7956Sxiuyan.wang@Sun.COM 
1314*7956Sxiuyan.wang@Sun.COM 	adapter->cmd_buf_arr = (struct unm_cmd_buffer *)kmem_zalloc(
1315*7956Sxiuyan.wang@Sun.COM 	    sizeof (struct unm_cmd_buffer) * adapter->MaxTxDescCount,
1316*7956Sxiuyan.wang@Sun.COM 	    KM_SLEEP);
1317*7956Sxiuyan.wang@Sun.COM 
1318*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < MAX_RCV_CTX; ++i) {
1319*7956Sxiuyan.wang@Sun.COM 		recv_ctx = &adapter->recv_ctx[i];
1320*7956Sxiuyan.wang@Sun.COM 
1321*7956Sxiuyan.wang@Sun.COM 		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1322*7956Sxiuyan.wang@Sun.COM 			rcv_desc = &recv_ctx->rcv_desc[ring];
1323*7956Sxiuyan.wang@Sun.COM 			ret = unm_create_rx_ring(adapter, rcv_desc);
1324*7956Sxiuyan.wang@Sun.COM 			if (ret != DDI_SUCCESS)
1325*7956Sxiuyan.wang@Sun.COM 				goto attach_free_cmdbufs;
1326*7956Sxiuyan.wang@Sun.COM 		}
1327*7956Sxiuyan.wang@Sun.COM 	}
1328*7956Sxiuyan.wang@Sun.COM 
1329*7956Sxiuyan.wang@Sun.COM 	ret = unm_alloc_tx_dmahdl(adapter);
1330*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS)
1331*7956Sxiuyan.wang@Sun.COM 		goto attach_free_cmdbufs;
1332*7956Sxiuyan.wang@Sun.COM 
1333*7956Sxiuyan.wang@Sun.COM 	ret = unm_alloc_tx_buffers(adapter);
1334*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS)
1335*7956Sxiuyan.wang@Sun.COM 		goto attach_free_tx_dmahdl;
1336*7956Sxiuyan.wang@Sun.COM 
1337*7956Sxiuyan.wang@Sun.COM 	adapter->ahw.linkup = 0;
1338*7956Sxiuyan.wang@Sun.COM 
1339*7956Sxiuyan.wang@Sun.COM 	if (receive_peg_ready(adapter)) {
1340*7956Sxiuyan.wang@Sun.COM 		ret = -EIO;
1341*7956Sxiuyan.wang@Sun.COM 		goto attach_free_tx_buffers;
1342*7956Sxiuyan.wang@Sun.COM 	}
1343*7956Sxiuyan.wang@Sun.COM 
1344*7956Sxiuyan.wang@Sun.COM 	if (netxen_read_mac_addr(adapter))
1345*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s%d: Failed to read MAC addr\n",
1346*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
1347*7956Sxiuyan.wang@Sun.COM 
1348*7956Sxiuyan.wang@Sun.COM 	unm_nic_flash_print(adapter);
1349*7956Sxiuyan.wang@Sun.COM 
1350*7956Sxiuyan.wang@Sun.COM 	if (verbmsg != 0) {
1351*7956Sxiuyan.wang@Sun.COM 		switch (adapter->ahw.board_type) {
1352*7956Sxiuyan.wang@Sun.COM 		case UNM_NIC_GBE:
1353*7956Sxiuyan.wang@Sun.COM 			cmn_err(CE_NOTE, "%s: QUAD GbE port %d initialized\n",
1354*7956Sxiuyan.wang@Sun.COM 			    unm_nic_driver_name, adapter->portnum);
1355*7956Sxiuyan.wang@Sun.COM 			break;
1356*7956Sxiuyan.wang@Sun.COM 
1357*7956Sxiuyan.wang@Sun.COM 		case UNM_NIC_XGBE:
1358*7956Sxiuyan.wang@Sun.COM 			cmn_err(CE_NOTE, "%s: XGbE port %d initialized\n",
1359*7956Sxiuyan.wang@Sun.COM 			    unm_nic_driver_name, adapter->portnum);
1360*7956Sxiuyan.wang@Sun.COM 			break;
1361*7956Sxiuyan.wang@Sun.COM 		}
1362*7956Sxiuyan.wang@Sun.COM 	}
1363*7956Sxiuyan.wang@Sun.COM 
1364*7956Sxiuyan.wang@Sun.COM 	ret = unm_register_mac(adapter);
1365*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
1366*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_NOTE, "%s%d: Mac registration error\n",
1367*7956Sxiuyan.wang@Sun.COM 		    adapter->name, adapter->instance);
1368*7956Sxiuyan.wang@Sun.COM 		goto attach_free_tx_buffers;
1369*7956Sxiuyan.wang@Sun.COM 	}
1370*7956Sxiuyan.wang@Sun.COM 
1371*7956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
1372*7956Sxiuyan.wang@Sun.COM 
1373*7956Sxiuyan.wang@Sun.COM attach_free_tx_buffers:
1374*7956Sxiuyan.wang@Sun.COM 	unm_free_tx_buffers(adapter);
1375*7956Sxiuyan.wang@Sun.COM attach_free_tx_dmahdl:
1376*7956Sxiuyan.wang@Sun.COM 	unm_free_tx_dmahdl(adapter);
1377*7956Sxiuyan.wang@Sun.COM attach_free_cmdbufs:
1378*7956Sxiuyan.wang@Sun.COM 	kmem_free(adapter->cmd_buf_arr, sizeof (struct unm_cmd_buffer) *
1379*7956Sxiuyan.wang@Sun.COM 	    adapter->MaxTxDescCount);
1380*7956Sxiuyan.wang@Sun.COM 	for (i = 0; i < MAX_RCV_CTX; ++i) {
1381*7956Sxiuyan.wang@Sun.COM 		recv_ctx = &adapter->recv_ctx[i];
1382*7956Sxiuyan.wang@Sun.COM 
1383*7956Sxiuyan.wang@Sun.COM 		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1384*7956Sxiuyan.wang@Sun.COM 			rcv_desc = &recv_ctx->rcv_desc[ring];
1385*7956Sxiuyan.wang@Sun.COM 			if (rcv_desc->rx_buf_pool != NULL)
1386*7956Sxiuyan.wang@Sun.COM 				unm_destroy_rx_ring(rcv_desc);
1387*7956Sxiuyan.wang@Sun.COM 		}
1388*7956Sxiuyan.wang@Sun.COM 	}
1389*7956Sxiuyan.wang@Sun.COM 
1390*7956Sxiuyan.wang@Sun.COM 	if (adapter->portnum == 0)
1391*7956Sxiuyan.wang@Sun.COM 		unm_free_dummy_dma(adapter);
1392*7956Sxiuyan.wang@Sun.COM attach_destroy_intr:
1393*7956Sxiuyan.wang@Sun.COM 	unm_destroy_intr(adapter);
1394*7956Sxiuyan.wang@Sun.COM attach_unmap_regs:
1395*7956Sxiuyan.wang@Sun.COM 	ddi_regs_map_free(&(adapter->regs_handle));
1396*7956Sxiuyan.wang@Sun.COM 	ddi_regs_map_free(&(adapter->db_handle));
1397*7956Sxiuyan.wang@Sun.COM attach_err:
1398*7956Sxiuyan.wang@Sun.COM 	pci_config_teardown(&adapter->pci_cfg_handle);
1399*7956Sxiuyan.wang@Sun.COM attach_setup_err:
1400*7956Sxiuyan.wang@Sun.COM 	kmem_free(adapter, sizeof (unm_adapter));
1401*7956Sxiuyan.wang@Sun.COM 	return (ret);
1402*7956Sxiuyan.wang@Sun.COM }
1403*7956Sxiuyan.wang@Sun.COM 
1404*7956Sxiuyan.wang@Sun.COM static int
1405*7956Sxiuyan.wang@Sun.COM unmdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1406*7956Sxiuyan.wang@Sun.COM {
1407*7956Sxiuyan.wang@Sun.COM 	unm_adapter  *adapter = (unm_adapter *)ddi_get_driver_private(dip);
1408*7956Sxiuyan.wang@Sun.COM 
1409*7956Sxiuyan.wang@Sun.COM 	if (adapter == NULL)
1410*7956Sxiuyan.wang@Sun.COM 	return (DDI_FAILURE);
1411*7956Sxiuyan.wang@Sun.COM 
1412*7956Sxiuyan.wang@Sun.COM 	switch (cmd) {
1413*7956Sxiuyan.wang@Sun.COM 	case DDI_DETACH:
1414*7956Sxiuyan.wang@Sun.COM 
1415*7956Sxiuyan.wang@Sun.COM 		unm_fini_kstats(adapter);
1416*7956Sxiuyan.wang@Sun.COM 		adapter->kstats[0] = NULL;
1417*7956Sxiuyan.wang@Sun.COM 
1418*7956Sxiuyan.wang@Sun.COM 		if (adapter->pci_cfg_handle != NULL)
1419*7956Sxiuyan.wang@Sun.COM 		pci_config_teardown(&adapter->pci_cfg_handle);
1420*7956Sxiuyan.wang@Sun.COM 
1421*7956Sxiuyan.wang@Sun.COM 		unm_nd_cleanup(adapter);
1422*7956Sxiuyan.wang@Sun.COM 		unm_nic_remove(adapter);
1423*7956Sxiuyan.wang@Sun.COM 		return (DDI_SUCCESS);
1424*7956Sxiuyan.wang@Sun.COM 
1425*7956Sxiuyan.wang@Sun.COM 	case DDI_SUSPEND:
1426*7956Sxiuyan.wang@Sun.COM 		return (unm_nic_suspend(adapter));
1427*7956Sxiuyan.wang@Sun.COM 
1428*7956Sxiuyan.wang@Sun.COM 	default:
1429*7956Sxiuyan.wang@Sun.COM 		break;
1430*7956Sxiuyan.wang@Sun.COM 	}
1431*7956Sxiuyan.wang@Sun.COM 
1432*7956Sxiuyan.wang@Sun.COM 	return (DDI_FAILURE);
1433*7956Sxiuyan.wang@Sun.COM }
1434*7956Sxiuyan.wang@Sun.COM 
1435*7956Sxiuyan.wang@Sun.COM #ifdef SOLARIS11
1436*7956Sxiuyan.wang@Sun.COM DDI_DEFINE_STREAM_OPS(unm_ops, nulldev, nulldev, unmattach, unmdetach,
1437*7956Sxiuyan.wang@Sun.COM 	nodev, NULL, D_MP, NULL, NULL);
1438*7956Sxiuyan.wang@Sun.COM #else
1439*7956Sxiuyan.wang@Sun.COM DDI_DEFINE_STREAM_OPS(unm_ops, nulldev, nulldev, unmattach, unmdetach,
1440*7956Sxiuyan.wang@Sun.COM 	nodev, NULL, D_MP, NULL);
1441*7956Sxiuyan.wang@Sun.COM #endif
1442*7956Sxiuyan.wang@Sun.COM 
1443*7956Sxiuyan.wang@Sun.COM static struct modldrv modldrv = {
1444*7956Sxiuyan.wang@Sun.COM 	&mod_driverops,	/* Type of module.  This one is a driver */
1445*7956Sxiuyan.wang@Sun.COM 	ident,
1446*7956Sxiuyan.wang@Sun.COM 	&unm_ops,	/* driver ops */
1447*7956Sxiuyan.wang@Sun.COM };
1448*7956Sxiuyan.wang@Sun.COM 
1449*7956Sxiuyan.wang@Sun.COM static struct modlinkage modlinkage = {
1450*7956Sxiuyan.wang@Sun.COM 	MODREV_1,
1451*7956Sxiuyan.wang@Sun.COM 	(&modldrv),
1452*7956Sxiuyan.wang@Sun.COM 	NULL
1453*7956Sxiuyan.wang@Sun.COM };
1454*7956Sxiuyan.wang@Sun.COM 
1455*7956Sxiuyan.wang@Sun.COM 
1456*7956Sxiuyan.wang@Sun.COM int
1457*7956Sxiuyan.wang@Sun.COM _init(void)
1458*7956Sxiuyan.wang@Sun.COM {
1459*7956Sxiuyan.wang@Sun.COM 	int ret;
1460*7956Sxiuyan.wang@Sun.COM 
1461*7956Sxiuyan.wang@Sun.COM 	unm_ops.devo_cb_ops->cb_str = NULL;
1462*7956Sxiuyan.wang@Sun.COM 	mac_init_ops(&unm_ops, "ntxn");
1463*7956Sxiuyan.wang@Sun.COM 
1464*7956Sxiuyan.wang@Sun.COM 	ret = mod_install(&modlinkage);
1465*7956Sxiuyan.wang@Sun.COM 	if (ret != DDI_SUCCESS) {
1466*7956Sxiuyan.wang@Sun.COM 		mac_fini_ops(&unm_ops);
1467*7956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "ntxn: mod_install failed\n");
1468*7956Sxiuyan.wang@Sun.COM 	}
1469*7956Sxiuyan.wang@Sun.COM 
1470*7956Sxiuyan.wang@Sun.COM 	return (ret);
1471*7956Sxiuyan.wang@Sun.COM }
1472*7956Sxiuyan.wang@Sun.COM 
1473*7956Sxiuyan.wang@Sun.COM 
1474*7956Sxiuyan.wang@Sun.COM int
1475*7956Sxiuyan.wang@Sun.COM _fini(void)
1476*7956Sxiuyan.wang@Sun.COM {
1477*7956Sxiuyan.wang@Sun.COM 	int ret;
1478*7956Sxiuyan.wang@Sun.COM 
1479*7956Sxiuyan.wang@Sun.COM 	ret = mod_remove(&modlinkage);
1480*7956Sxiuyan.wang@Sun.COM 	if (ret == DDI_SUCCESS)
1481*7956Sxiuyan.wang@Sun.COM 		mac_fini_ops(&unm_ops);
1482*7956Sxiuyan.wang@Sun.COM 	return (ret);
1483*7956Sxiuyan.wang@Sun.COM }
1484*7956Sxiuyan.wang@Sun.COM 
1485*7956Sxiuyan.wang@Sun.COM int
1486*7956Sxiuyan.wang@Sun.COM _info(struct modinfo *modinfop)
1487*7956Sxiuyan.wang@Sun.COM {
1488*7956Sxiuyan.wang@Sun.COM 	return (mod_info(&modlinkage, modinfop));
1489*7956Sxiuyan.wang@Sun.COM }
1490