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