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