17956Sxiuyan.wang@Sun.COM /*
27956Sxiuyan.wang@Sun.COM * CDDL HEADER START
37956Sxiuyan.wang@Sun.COM *
47956Sxiuyan.wang@Sun.COM * The contents of this file are subject to the terms of the
57956Sxiuyan.wang@Sun.COM * Common Development and Distribution License (the "License").
67956Sxiuyan.wang@Sun.COM * You may not use this file except in compliance with the License.
77956Sxiuyan.wang@Sun.COM *
87956Sxiuyan.wang@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97956Sxiuyan.wang@Sun.COM * or http://www.opensolaris.org/os/licensing.
107956Sxiuyan.wang@Sun.COM * See the License for the specific language governing permissions
117956Sxiuyan.wang@Sun.COM * and limitations under the License.
127956Sxiuyan.wang@Sun.COM *
137956Sxiuyan.wang@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147956Sxiuyan.wang@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157956Sxiuyan.wang@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167956Sxiuyan.wang@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177956Sxiuyan.wang@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187956Sxiuyan.wang@Sun.COM *
197956Sxiuyan.wang@Sun.COM * CDDL HEADER END
207956Sxiuyan.wang@Sun.COM */
217956Sxiuyan.wang@Sun.COM /*
227956Sxiuyan.wang@Sun.COM * Copyright 2008 NetXen, Inc. All rights reserved.
237956Sxiuyan.wang@Sun.COM * Use is subject to license terms.
247956Sxiuyan.wang@Sun.COM */
257956Sxiuyan.wang@Sun.COM /*
268687SJing.Xiong@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
277956Sxiuyan.wang@Sun.COM * Use is subject to license terms.
287956Sxiuyan.wang@Sun.COM */
297956Sxiuyan.wang@Sun.COM #include <sys/types.h>
307956Sxiuyan.wang@Sun.COM #include <sys/conf.h>
317956Sxiuyan.wang@Sun.COM #include <sys/debug.h>
327956Sxiuyan.wang@Sun.COM #include <sys/stropts.h>
337956Sxiuyan.wang@Sun.COM #include <sys/stream.h>
347956Sxiuyan.wang@Sun.COM #include <sys/strlog.h>
357956Sxiuyan.wang@Sun.COM #include <sys/kmem.h>
367956Sxiuyan.wang@Sun.COM #include <sys/stat.h>
377956Sxiuyan.wang@Sun.COM #include <sys/kstat.h>
387956Sxiuyan.wang@Sun.COM #include <sys/vtrace.h>
397956Sxiuyan.wang@Sun.COM #include <sys/dlpi.h>
407956Sxiuyan.wang@Sun.COM #include <sys/strsun.h>
417956Sxiuyan.wang@Sun.COM #include <sys/ethernet.h>
427956Sxiuyan.wang@Sun.COM #include <sys/modctl.h>
437956Sxiuyan.wang@Sun.COM #include <sys/errno.h>
447956Sxiuyan.wang@Sun.COM #include <sys/dditypes.h>
457956Sxiuyan.wang@Sun.COM #include <sys/ddi.h>
467956Sxiuyan.wang@Sun.COM #include <sys/sunddi.h>
477956Sxiuyan.wang@Sun.COM #include <sys/sysmacros.h>
487956Sxiuyan.wang@Sun.COM #include <sys/pci.h>
497956Sxiuyan.wang@Sun.COM #include <sys/ddi_intr.h>
507956Sxiuyan.wang@Sun.COM
517956Sxiuyan.wang@Sun.COM #include "unm_nic.h"
527956Sxiuyan.wang@Sun.COM #include "unm_nic_hw.h"
537956Sxiuyan.wang@Sun.COM #include "unm_brdcfg.h"
547956Sxiuyan.wang@Sun.COM #include "nic_cmn.h"
557956Sxiuyan.wang@Sun.COM #include "nic_phan_reg.h"
567956Sxiuyan.wang@Sun.COM #include "unm_nic_ioctl.h"
577956Sxiuyan.wang@Sun.COM #include "nx_hw_pci_regs.h"
587956Sxiuyan.wang@Sun.COM
597956Sxiuyan.wang@Sun.COM char ident[] = "Netxen nic driver v" UNM_NIC_VERSIONID;
607956Sxiuyan.wang@Sun.COM char unm_nic_driver_name[] = "ntxn";
617956Sxiuyan.wang@Sun.COM int verbmsg = 0;
627956Sxiuyan.wang@Sun.COM
637956Sxiuyan.wang@Sun.COM static char txbcopythreshold_propname[] = "tx_bcopy_threshold";
647956Sxiuyan.wang@Sun.COM static char rxbcopythreshold_propname[] = "rx_bcopy_threshold";
657956Sxiuyan.wang@Sun.COM static char rxringsize_propname[] = "rx_ring_size";
667956Sxiuyan.wang@Sun.COM static char jumborxringsize_propname[] = "jumbo_rx_ring_size";
677956Sxiuyan.wang@Sun.COM static char txringsize_propname[] = "tx_ring_size";
687956Sxiuyan.wang@Sun.COM static char defaultmtu_propname[] = "default_mtu";
697956Sxiuyan.wang@Sun.COM static char dmesg_propname[] = "verbose_driver";
707956Sxiuyan.wang@Sun.COM
717956Sxiuyan.wang@Sun.COM #define STRUCT_COPY(a, b) bcopy(&(b), &(a), sizeof (a))
727956Sxiuyan.wang@Sun.COM
737956Sxiuyan.wang@Sun.COM extern int unm_register_mac(unm_adapter *adapter);
747956Sxiuyan.wang@Sun.COM extern void unm_fini_kstats(unm_adapter* adapter);
757956Sxiuyan.wang@Sun.COM extern void unm_nic_remove(unm_adapter *adapter);
767956Sxiuyan.wang@Sun.COM extern int unm_nic_suspend(unm_adapter *);
777956Sxiuyan.wang@Sun.COM extern uint_t unm_intr(caddr_t, caddr_t);
787956Sxiuyan.wang@Sun.COM
797956Sxiuyan.wang@Sun.COM /* Data access requirements. */
807956Sxiuyan.wang@Sun.COM static struct ddi_device_acc_attr unm_dev_attr = {
817956Sxiuyan.wang@Sun.COM DDI_DEVICE_ATTR_V0,
827956Sxiuyan.wang@Sun.COM DDI_STRUCTURE_LE_ACC,
837956Sxiuyan.wang@Sun.COM DDI_STRICTORDER_ACC
847956Sxiuyan.wang@Sun.COM };
857956Sxiuyan.wang@Sun.COM
867956Sxiuyan.wang@Sun.COM static struct ddi_device_acc_attr unm_buf_attr = {
877956Sxiuyan.wang@Sun.COM DDI_DEVICE_ATTR_V0,
887956Sxiuyan.wang@Sun.COM DDI_NEVERSWAP_ACC,
897956Sxiuyan.wang@Sun.COM DDI_STRICTORDER_ACC
907956Sxiuyan.wang@Sun.COM };
917956Sxiuyan.wang@Sun.COM
927956Sxiuyan.wang@Sun.COM static ddi_dma_attr_t unm_dma_attr_desc = {
937956Sxiuyan.wang@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
947956Sxiuyan.wang@Sun.COM 0, /* dma_attr_addr_lo */
957956Sxiuyan.wang@Sun.COM 0xffffffffull, /* dma_attr_addr_hi */
967956Sxiuyan.wang@Sun.COM 0x000fffffull, /* dma_attr_count_max */
977956Sxiuyan.wang@Sun.COM 4096, /* dma_attr_align */
987956Sxiuyan.wang@Sun.COM 0x000fffffull, /* dma_attr_burstsizes */
997956Sxiuyan.wang@Sun.COM 4, /* dma_attr_minxfer */
1007956Sxiuyan.wang@Sun.COM 0x003fffffull, /* dma_attr_maxxfer */
1017956Sxiuyan.wang@Sun.COM 0xffffffffull, /* dma_attr_seg */
1027956Sxiuyan.wang@Sun.COM 1, /* dma_attr_sgllen */
1037956Sxiuyan.wang@Sun.COM 1, /* dma_attr_granular */
1047956Sxiuyan.wang@Sun.COM 0 /* dma_attr_flags */
1057956Sxiuyan.wang@Sun.COM };
1067956Sxiuyan.wang@Sun.COM
1077956Sxiuyan.wang@Sun.COM static ddi_dma_attr_t unm_dma_attr_rxbuf = {
1087956Sxiuyan.wang@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
1097956Sxiuyan.wang@Sun.COM 0, /* dma_attr_addr_lo */
1107956Sxiuyan.wang@Sun.COM 0x7ffffffffULL, /* dma_attr_addr_hi */
1117956Sxiuyan.wang@Sun.COM 0xffffull, /* dma_attr_count_max */
1127956Sxiuyan.wang@Sun.COM 4096, /* dma_attr_align */
1137956Sxiuyan.wang@Sun.COM 0xfff8ull, /* dma_attr_burstsizes */
1147956Sxiuyan.wang@Sun.COM 1, /* dma_attr_minxfer */
1157956Sxiuyan.wang@Sun.COM 0xffffffffull, /* dma_attr_maxxfer */
1167956Sxiuyan.wang@Sun.COM 0xffffull, /* dma_attr_seg */
1177956Sxiuyan.wang@Sun.COM 1, /* dma_attr_sgllen */
1187956Sxiuyan.wang@Sun.COM 1, /* dma_attr_granular */
1197956Sxiuyan.wang@Sun.COM 0 /* dma_attr_flags */
1207956Sxiuyan.wang@Sun.COM };
1217956Sxiuyan.wang@Sun.COM
1227956Sxiuyan.wang@Sun.COM static ddi_dma_attr_t unm_dma_attr_cmddesc = {
1237956Sxiuyan.wang@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
1247956Sxiuyan.wang@Sun.COM 0, /* dma_attr_addr_lo */
1257956Sxiuyan.wang@Sun.COM 0x7ffffffffULL, /* dma_attr_addr_hi */
1267956Sxiuyan.wang@Sun.COM 0xffffull, /* dma_attr_count_max */
1277956Sxiuyan.wang@Sun.COM 1, /* dma_attr_align */
1287956Sxiuyan.wang@Sun.COM 0xfff8ull, /* dma_attr_burstsizes */
1297956Sxiuyan.wang@Sun.COM 1, /* dma_attr_minxfer */
1307956Sxiuyan.wang@Sun.COM 0xffff0ull, /* dma_attr_maxxfer */
1317956Sxiuyan.wang@Sun.COM 0xffffull, /* dma_attr_seg */
1327956Sxiuyan.wang@Sun.COM 16, /* dma_attr_sgllen */
1337956Sxiuyan.wang@Sun.COM 1, /* dma_attr_granular */
1347956Sxiuyan.wang@Sun.COM 0 /* dma_attr_flags */
1357956Sxiuyan.wang@Sun.COM };
1367956Sxiuyan.wang@Sun.COM
1377956Sxiuyan.wang@Sun.COM static struct nx_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
1387956Sxiuyan.wang@Sun.COM
1397956Sxiuyan.wang@Sun.COM static int
check_hw_init(struct unm_adapter_s * adapter)1407956Sxiuyan.wang@Sun.COM check_hw_init(struct unm_adapter_s *adapter)
1417956Sxiuyan.wang@Sun.COM {
1427956Sxiuyan.wang@Sun.COM u32 val;
1437956Sxiuyan.wang@Sun.COM int ret = 0;
1447956Sxiuyan.wang@Sun.COM
1457956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_read_wx(adapter, UNM_CAM_RAM(0x1fc), &val, 4);
1467956Sxiuyan.wang@Sun.COM if (val == 0x55555555) {
1477956Sxiuyan.wang@Sun.COM /* This is the first boot after power up */
1487956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_read_wx(adapter, UNM_ROMUSB_GLB_SW_RESET,
1497956Sxiuyan.wang@Sun.COM &val, 4);
1507956Sxiuyan.wang@Sun.COM if (val != 0x80000f)
1517956Sxiuyan.wang@Sun.COM ret = -1;
1527956Sxiuyan.wang@Sun.COM
1537956Sxiuyan.wang@Sun.COM if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
1547956Sxiuyan.wang@Sun.COM /* Start P2 boot loader */
1557956Sxiuyan.wang@Sun.COM adapter->unm_nic_pci_write_normalize(adapter,
1567956Sxiuyan.wang@Sun.COM UNM_CAM_RAM(0x1fc), UNM_BDINFO_MAGIC);
1577956Sxiuyan.wang@Sun.COM adapter->unm_nic_pci_write_normalize(adapter,
1587956Sxiuyan.wang@Sun.COM UNM_ROMUSB_GLB_PEGTUNE_DONE, 1);
1597956Sxiuyan.wang@Sun.COM }
1607956Sxiuyan.wang@Sun.COM }
1617956Sxiuyan.wang@Sun.COM return (ret);
1627956Sxiuyan.wang@Sun.COM }
1637956Sxiuyan.wang@Sun.COM
1647956Sxiuyan.wang@Sun.COM
1657956Sxiuyan.wang@Sun.COM static int
unm_get_flash_block(unm_adapter * adapter,int base,int size,uint32_t * buf)1667956Sxiuyan.wang@Sun.COM unm_get_flash_block(unm_adapter *adapter, int base, int size, uint32_t *buf)
1677956Sxiuyan.wang@Sun.COM {
1687956Sxiuyan.wang@Sun.COM int i, addr;
1697956Sxiuyan.wang@Sun.COM uint32_t *ptr32;
1707956Sxiuyan.wang@Sun.COM
1717956Sxiuyan.wang@Sun.COM addr = base;
1727956Sxiuyan.wang@Sun.COM ptr32 = buf;
1737956Sxiuyan.wang@Sun.COM for (i = 0; i < size / sizeof (uint32_t); i++) {
1747956Sxiuyan.wang@Sun.COM if (rom_fast_read(adapter, addr, (int *)ptr32) == -1)
1757956Sxiuyan.wang@Sun.COM return (-1);
1767956Sxiuyan.wang@Sun.COM ptr32++;
1777956Sxiuyan.wang@Sun.COM addr += sizeof (uint32_t);
1787956Sxiuyan.wang@Sun.COM }
1797956Sxiuyan.wang@Sun.COM if ((char *)buf + size > (char *)ptr32) {
1807956Sxiuyan.wang@Sun.COM int local;
1817956Sxiuyan.wang@Sun.COM
1827956Sxiuyan.wang@Sun.COM if (rom_fast_read(adapter, addr, &local) == -1)
1837956Sxiuyan.wang@Sun.COM return (-1);
1847956Sxiuyan.wang@Sun.COM (void) memcpy(ptr32, &local,
1857956Sxiuyan.wang@Sun.COM (uintptr_t)((char *)buf + size) - (uintptr_t)(char *)ptr32);
1867956Sxiuyan.wang@Sun.COM }
1877956Sxiuyan.wang@Sun.COM
1887956Sxiuyan.wang@Sun.COM return (0);
1897956Sxiuyan.wang@Sun.COM }
1907956Sxiuyan.wang@Sun.COM
1917956Sxiuyan.wang@Sun.COM
1927956Sxiuyan.wang@Sun.COM static int
get_flash_mac_addr(struct unm_adapter_s * adapter,u64 mac[])1937956Sxiuyan.wang@Sun.COM get_flash_mac_addr(struct unm_adapter_s *adapter, u64 mac[])
1947956Sxiuyan.wang@Sun.COM {
1957956Sxiuyan.wang@Sun.COM uint32_t *pmac = (uint32_t *)&mac[0];
1967956Sxiuyan.wang@Sun.COM
1977956Sxiuyan.wang@Sun.COM if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
1987956Sxiuyan.wang@Sun.COM uint32_t temp, crbaddr;
1997956Sxiuyan.wang@Sun.COM uint16_t *pmac16 = (uint16_t *)pmac;
2007956Sxiuyan.wang@Sun.COM
2017956Sxiuyan.wang@Sun.COM // FOR P3, read from CAM RAM
2027956Sxiuyan.wang@Sun.COM
2037956Sxiuyan.wang@Sun.COM int pci_func = adapter->ahw.pci_func;
2048687SJing.Xiong@Sun.COM pmac16 += (4 * pci_func);
2057956Sxiuyan.wang@Sun.COM crbaddr = CRB_MAC_BLOCK_START + (4 * ((pci_func/2) * 3)) +
2067956Sxiuyan.wang@Sun.COM (4 * (pci_func & 1));
2077956Sxiuyan.wang@Sun.COM
2087956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_read_wx(adapter, crbaddr, &temp, 4);
2097956Sxiuyan.wang@Sun.COM if (pci_func & 1) {
2107956Sxiuyan.wang@Sun.COM *pmac16++ = (temp >> 16);
2117956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_read_wx(adapter, crbaddr+4,
2127956Sxiuyan.wang@Sun.COM &temp, 4);
2137956Sxiuyan.wang@Sun.COM *pmac16++ = (temp & 0xffff);
2147956Sxiuyan.wang@Sun.COM *pmac16++ = (temp >> 16);
2157956Sxiuyan.wang@Sun.COM *pmac16 = 0;
2167956Sxiuyan.wang@Sun.COM } else {
2177956Sxiuyan.wang@Sun.COM *pmac16++ = (temp & 0xffff);
2187956Sxiuyan.wang@Sun.COM *pmac16++ = (temp >> 16);
2197956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_read_wx(adapter, crbaddr+4,
2207956Sxiuyan.wang@Sun.COM &temp, 4);
2217956Sxiuyan.wang@Sun.COM *pmac16++ = (temp & 0xffff);
2227956Sxiuyan.wang@Sun.COM *pmac16 = 0;
2237956Sxiuyan.wang@Sun.COM }
2247956Sxiuyan.wang@Sun.COM return (0);
2257956Sxiuyan.wang@Sun.COM }
2267956Sxiuyan.wang@Sun.COM
2277956Sxiuyan.wang@Sun.COM
2287956Sxiuyan.wang@Sun.COM if (unm_get_flash_block(adapter, USER_START +
2297956Sxiuyan.wang@Sun.COM offsetof(unm_user_info_t, mac_addr), FLASH_NUM_PORTS * sizeof (U64),
2307956Sxiuyan.wang@Sun.COM pmac) == -1)
2317956Sxiuyan.wang@Sun.COM return (-1);
2327956Sxiuyan.wang@Sun.COM
2337956Sxiuyan.wang@Sun.COM if (*mac == ~0ULL) {
2347956Sxiuyan.wang@Sun.COM if (unm_get_flash_block(adapter, USER_START_OLD +
2357956Sxiuyan.wang@Sun.COM offsetof(unm_old_user_info_t, mac_addr),
2367956Sxiuyan.wang@Sun.COM FLASH_NUM_PORTS * sizeof (U64), pmac) == -1)
2377956Sxiuyan.wang@Sun.COM return (-1);
2387956Sxiuyan.wang@Sun.COM
2397956Sxiuyan.wang@Sun.COM if (*mac == ~0ULL)
2407956Sxiuyan.wang@Sun.COM return (-1);
2417956Sxiuyan.wang@Sun.COM }
2427956Sxiuyan.wang@Sun.COM
2437956Sxiuyan.wang@Sun.COM return (0);
2447956Sxiuyan.wang@Sun.COM }
2457956Sxiuyan.wang@Sun.COM
2467956Sxiuyan.wang@Sun.COM static int
unm_initialize_dummy_dma(unm_adapter * adapter)2477956Sxiuyan.wang@Sun.COM unm_initialize_dummy_dma(unm_adapter *adapter)
2487956Sxiuyan.wang@Sun.COM {
2497956Sxiuyan.wang@Sun.COM uint32_t hi, lo, temp;
2507956Sxiuyan.wang@Sun.COM ddi_dma_cookie_t cookie;
2517956Sxiuyan.wang@Sun.COM
2527956Sxiuyan.wang@Sun.COM if (unm_pci_alloc_consistent(adapter, UNM_HOST_DUMMY_DMA_SIZE,
2537956Sxiuyan.wang@Sun.COM (caddr_t *)&adapter->dummy_dma.addr, &cookie,
2547956Sxiuyan.wang@Sun.COM &adapter->dummy_dma.dma_handle,
2557956Sxiuyan.wang@Sun.COM &adapter->dummy_dma.acc_handle) != DDI_SUCCESS) {
2567956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: Unable to alloc dummy dma buf\n",
2577956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
2587956Sxiuyan.wang@Sun.COM return (DDI_ENOMEM);
2597956Sxiuyan.wang@Sun.COM }
2607956Sxiuyan.wang@Sun.COM
2617956Sxiuyan.wang@Sun.COM adapter->dummy_dma.phys_addr = cookie.dmac_laddress;
2627956Sxiuyan.wang@Sun.COM
2637956Sxiuyan.wang@Sun.COM hi = (adapter->dummy_dma.phys_addr >> 32) & 0xffffffff;
2647956Sxiuyan.wang@Sun.COM lo = adapter->dummy_dma.phys_addr & 0xffffffff;
2657956Sxiuyan.wang@Sun.COM
2667956Sxiuyan.wang@Sun.COM UNM_READ_LOCK(&adapter->adapter_lock);
2677956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI,
2687956Sxiuyan.wang@Sun.COM &hi, 4);
2697956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO,
2707956Sxiuyan.wang@Sun.COM &lo, 4);
2717956Sxiuyan.wang@Sun.COM if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
2727956Sxiuyan.wang@Sun.COM temp = DUMMY_BUF_INIT;
2737956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF,
2747956Sxiuyan.wang@Sun.COM &temp, 4);
2757956Sxiuyan.wang@Sun.COM }
2767956Sxiuyan.wang@Sun.COM UNM_READ_UNLOCK(&adapter->adapter_lock);
2777956Sxiuyan.wang@Sun.COM
2787956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
2797956Sxiuyan.wang@Sun.COM }
2807956Sxiuyan.wang@Sun.COM
2817956Sxiuyan.wang@Sun.COM void
unm_free_dummy_dma(unm_adapter * adapter)2827956Sxiuyan.wang@Sun.COM unm_free_dummy_dma(unm_adapter *adapter)
2837956Sxiuyan.wang@Sun.COM {
2847956Sxiuyan.wang@Sun.COM if (adapter->dummy_dma.addr) {
2857956Sxiuyan.wang@Sun.COM unm_pci_free_consistent(&adapter->dummy_dma.dma_handle,
2867956Sxiuyan.wang@Sun.COM &adapter->dummy_dma.acc_handle);
2877956Sxiuyan.wang@Sun.COM adapter->dummy_dma.addr = NULL;
2887956Sxiuyan.wang@Sun.COM }
2897956Sxiuyan.wang@Sun.COM }
2907956Sxiuyan.wang@Sun.COM
2917956Sxiuyan.wang@Sun.COM static int
unm_pci_cfg_init(unm_adapter * adapter)2927956Sxiuyan.wang@Sun.COM unm_pci_cfg_init(unm_adapter *adapter)
2937956Sxiuyan.wang@Sun.COM {
2947956Sxiuyan.wang@Sun.COM hardware_context *hwcontext;
2957956Sxiuyan.wang@Sun.COM ddi_acc_handle_t pci_cfg_hdl;
2967956Sxiuyan.wang@Sun.COM int *reg_options;
2977956Sxiuyan.wang@Sun.COM dev_info_t *dip;
2987956Sxiuyan.wang@Sun.COM uint_t noptions;
2997956Sxiuyan.wang@Sun.COM int ret;
3007956Sxiuyan.wang@Sun.COM uint16_t vendor_id, pci_cmd_word;
3017956Sxiuyan.wang@Sun.COM uint8_t base_class, sub_class, prog_class;
3027956Sxiuyan.wang@Sun.COM uint32_t pexsizes;
3037956Sxiuyan.wang@Sun.COM struct nx_legacy_intr_set *legacy_intrp;
3047956Sxiuyan.wang@Sun.COM
3057956Sxiuyan.wang@Sun.COM hwcontext = &adapter->ahw;
3067956Sxiuyan.wang@Sun.COM pci_cfg_hdl = adapter->pci_cfg_handle;
3077956Sxiuyan.wang@Sun.COM dip = adapter->dip;
3087956Sxiuyan.wang@Sun.COM
3097956Sxiuyan.wang@Sun.COM vendor_id = pci_config_get16(pci_cfg_hdl, PCI_CONF_VENID);
3107956Sxiuyan.wang@Sun.COM
3117956Sxiuyan.wang@Sun.COM if (vendor_id != 0x4040) {
3127956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: vendor id %x not 0x4040\n",
3137956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance, vendor_id);
3147956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
3157956Sxiuyan.wang@Sun.COM }
3167956Sxiuyan.wang@Sun.COM
3177956Sxiuyan.wang@Sun.COM ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
3187956Sxiuyan.wang@Sun.COM dip, 0, "reg", ®_options, &noptions);
3197956Sxiuyan.wang@Sun.COM if (ret != DDI_PROP_SUCCESS) {
3207956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: Could not determine reg property\n",
3217956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
3227956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
3237956Sxiuyan.wang@Sun.COM }
3247956Sxiuyan.wang@Sun.COM
3257956Sxiuyan.wang@Sun.COM hwcontext->pci_func = (reg_options[0] >> 8) & 0x7;
3267956Sxiuyan.wang@Sun.COM ddi_prop_free(reg_options);
3277956Sxiuyan.wang@Sun.COM
3287956Sxiuyan.wang@Sun.COM base_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_BASCLASS);
3297956Sxiuyan.wang@Sun.COM sub_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_SUBCLASS);
3307956Sxiuyan.wang@Sun.COM prog_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_PROGCLASS);
3317956Sxiuyan.wang@Sun.COM
3327956Sxiuyan.wang@Sun.COM /*
3337956Sxiuyan.wang@Sun.COM * Need this check so that MEZZ card mgmt interface ntxn0 could fail
3347956Sxiuyan.wang@Sun.COM * attach & return and proceed to next interfaces ntxn1 and ntxn2
3357956Sxiuyan.wang@Sun.COM */
3367956Sxiuyan.wang@Sun.COM if ((base_class != 0x02) || (sub_class != 0) || (prog_class != 0)) {
3377956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: Base/sub/prog class problem %d/%d/%d\n",
3387956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance, base_class, sub_class,
3397956Sxiuyan.wang@Sun.COM prog_class);
3407956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
3417956Sxiuyan.wang@Sun.COM }
3427956Sxiuyan.wang@Sun.COM
3437956Sxiuyan.wang@Sun.COM hwcontext->revision_id = pci_config_get8(pci_cfg_hdl, PCI_CONF_REVID);
3447956Sxiuyan.wang@Sun.COM
3457956Sxiuyan.wang@Sun.COM /*
3467956Sxiuyan.wang@Sun.COM * Refuse to work with dubious P3 cards.
3477956Sxiuyan.wang@Sun.COM */
3487956Sxiuyan.wang@Sun.COM if ((hwcontext->revision_id >= NX_P3_A0) &&
3497956Sxiuyan.wang@Sun.COM (hwcontext->revision_id < NX_P3_B1)) {
3507956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: NetXen chip revs between 0x%x-0x%x "
3517956Sxiuyan.wang@Sun.COM "is unsupported\n", adapter->name, adapter->instance,
3527956Sxiuyan.wang@Sun.COM NX_P3_A0, NX_P3_B0);
3537956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
3547956Sxiuyan.wang@Sun.COM }
3557956Sxiuyan.wang@Sun.COM
3567956Sxiuyan.wang@Sun.COM /*
3577956Sxiuyan.wang@Sun.COM * Save error reporting settings; clear [19:16] error status bits.
3587956Sxiuyan.wang@Sun.COM * Set max read request [14:12] to 0 for 128 bytes. Set max payload
3597956Sxiuyan.wang@Sun.COM * size[7:5] to 0 for for 128 bytes.
3607956Sxiuyan.wang@Sun.COM */
3617956Sxiuyan.wang@Sun.COM if (NX_IS_REVISION_P2(hwcontext->revision_id)) {
3627956Sxiuyan.wang@Sun.COM pexsizes = pci_config_get32(pci_cfg_hdl, 0xd8);
3637956Sxiuyan.wang@Sun.COM pexsizes &= 7;
3647956Sxiuyan.wang@Sun.COM pexsizes |= 0xF0000;
3657956Sxiuyan.wang@Sun.COM pci_config_put32(pci_cfg_hdl, 0xd8, pexsizes);
3667956Sxiuyan.wang@Sun.COM }
3677956Sxiuyan.wang@Sun.COM
3687956Sxiuyan.wang@Sun.COM pci_cmd_word = pci_config_get16(pci_cfg_hdl, PCI_CONF_COMM);
3697956Sxiuyan.wang@Sun.COM pci_cmd_word |= (PCI_COMM_INTX_DISABLE | PCI_COMM_SERR_ENABLE);
3707956Sxiuyan.wang@Sun.COM pci_config_put16(pci_cfg_hdl, PCI_CONF_COMM, pci_cmd_word);
3717956Sxiuyan.wang@Sun.COM
3727956Sxiuyan.wang@Sun.COM if (hwcontext->revision_id >= NX_P3_B0)
3737956Sxiuyan.wang@Sun.COM legacy_intrp = &legacy_intr[hwcontext->pci_func];
3747956Sxiuyan.wang@Sun.COM else
3757956Sxiuyan.wang@Sun.COM legacy_intrp = &legacy_intr[0];
3767956Sxiuyan.wang@Sun.COM
3777956Sxiuyan.wang@Sun.COM adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit;
3787956Sxiuyan.wang@Sun.COM adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg;
3797956Sxiuyan.wang@Sun.COM adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg;
3807956Sxiuyan.wang@Sun.COM adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg;
3817956Sxiuyan.wang@Sun.COM
3827956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
3837956Sxiuyan.wang@Sun.COM }
3847956Sxiuyan.wang@Sun.COM
385*9436SJing.Xiong@Sun.COM static void
unm_free_tx_dmahdl(unm_adapter * adapter)3867956Sxiuyan.wang@Sun.COM unm_free_tx_dmahdl(unm_adapter *adapter)
3877956Sxiuyan.wang@Sun.COM {
3887956Sxiuyan.wang@Sun.COM int i;
3897956Sxiuyan.wang@Sun.COM unm_dmah_node_t *nodep;
3907956Sxiuyan.wang@Sun.COM
3917956Sxiuyan.wang@Sun.COM mutex_enter(&adapter->tx_lock);
3927956Sxiuyan.wang@Sun.COM nodep = &adapter->tx_dma_hdls[0];
3937956Sxiuyan.wang@Sun.COM
3947956Sxiuyan.wang@Sun.COM for (i = 0; i < adapter->MaxTxDescCount + EXTRA_HANDLES; i++) {
3957956Sxiuyan.wang@Sun.COM if (nodep->dmahdl != NULL) {
3967956Sxiuyan.wang@Sun.COM ddi_dma_free_handle(&nodep->dmahdl);
3977956Sxiuyan.wang@Sun.COM nodep->dmahdl = NULL;
3987956Sxiuyan.wang@Sun.COM }
3997956Sxiuyan.wang@Sun.COM nodep->next = NULL;
4007956Sxiuyan.wang@Sun.COM nodep++;
4017956Sxiuyan.wang@Sun.COM }
4027956Sxiuyan.wang@Sun.COM
4037956Sxiuyan.wang@Sun.COM adapter->dmahdl_pool = NULL;
4047956Sxiuyan.wang@Sun.COM adapter->freehdls = 0;
4057956Sxiuyan.wang@Sun.COM mutex_exit(&adapter->tx_lock);
4067956Sxiuyan.wang@Sun.COM }
4077956Sxiuyan.wang@Sun.COM
4087956Sxiuyan.wang@Sun.COM static int
unm_alloc_tx_dmahdl(unm_adapter * adapter)4097956Sxiuyan.wang@Sun.COM unm_alloc_tx_dmahdl(unm_adapter *adapter)
4107956Sxiuyan.wang@Sun.COM {
4117956Sxiuyan.wang@Sun.COM int i;
4127956Sxiuyan.wang@Sun.COM unm_dmah_node_t *nodep = &adapter->tx_dma_hdls[0];
4137956Sxiuyan.wang@Sun.COM
4147956Sxiuyan.wang@Sun.COM mutex_enter(&adapter->tx_lock);
4157956Sxiuyan.wang@Sun.COM for (i = 0; i < adapter->MaxTxDescCount + EXTRA_HANDLES; i++) {
4167956Sxiuyan.wang@Sun.COM if (ddi_dma_alloc_handle(adapter->dip, &unm_dma_attr_cmddesc,
4177956Sxiuyan.wang@Sun.COM DDI_DMA_DONTWAIT, NULL, &nodep->dmahdl) != DDI_SUCCESS) {
4187956Sxiuyan.wang@Sun.COM mutex_exit(&adapter->tx_lock);
4197956Sxiuyan.wang@Sun.COM goto alloc_hdl_fail;
4207956Sxiuyan.wang@Sun.COM }
4217956Sxiuyan.wang@Sun.COM
4227956Sxiuyan.wang@Sun.COM if (i > 0)
4237956Sxiuyan.wang@Sun.COM nodep->next = nodep - 1;
4247956Sxiuyan.wang@Sun.COM nodep++;
4257956Sxiuyan.wang@Sun.COM }
4267956Sxiuyan.wang@Sun.COM
4277956Sxiuyan.wang@Sun.COM adapter->dmahdl_pool = nodep - 1;
4287956Sxiuyan.wang@Sun.COM adapter->freehdls = i;
4297956Sxiuyan.wang@Sun.COM mutex_exit(&adapter->tx_lock);
4307956Sxiuyan.wang@Sun.COM
4317956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
4327956Sxiuyan.wang@Sun.COM
4337956Sxiuyan.wang@Sun.COM alloc_hdl_fail:
4347956Sxiuyan.wang@Sun.COM unm_free_tx_dmahdl(adapter);
4357956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: Failed transmit ring dma handle allocation\n",
4367956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
4377956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
4387956Sxiuyan.wang@Sun.COM }
4397956Sxiuyan.wang@Sun.COM
4407956Sxiuyan.wang@Sun.COM static void
unm_free_dma_mem(dma_area_t * dma_p)4417956Sxiuyan.wang@Sun.COM unm_free_dma_mem(dma_area_t *dma_p)
4427956Sxiuyan.wang@Sun.COM {
4437956Sxiuyan.wang@Sun.COM if (dma_p->dma_hdl != NULL) {
4447956Sxiuyan.wang@Sun.COM if (dma_p->ncookies) {
4457956Sxiuyan.wang@Sun.COM (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
4467956Sxiuyan.wang@Sun.COM dma_p->ncookies = 0;
4477956Sxiuyan.wang@Sun.COM }
4487956Sxiuyan.wang@Sun.COM }
4497956Sxiuyan.wang@Sun.COM if (dma_p->acc_hdl != NULL) {
4507956Sxiuyan.wang@Sun.COM ddi_dma_mem_free(&dma_p->acc_hdl);
4517956Sxiuyan.wang@Sun.COM dma_p->acc_hdl = NULL;
4527956Sxiuyan.wang@Sun.COM }
4537956Sxiuyan.wang@Sun.COM if (dma_p->dma_hdl != NULL) {
4547956Sxiuyan.wang@Sun.COM ddi_dma_free_handle(&dma_p->dma_hdl);
4557956Sxiuyan.wang@Sun.COM dma_p->dma_hdl = NULL;
4567956Sxiuyan.wang@Sun.COM }
4577956Sxiuyan.wang@Sun.COM }
4587956Sxiuyan.wang@Sun.COM
4597956Sxiuyan.wang@Sun.COM static int
unm_alloc_dma_mem(unm_adapter * adapter,int size,uint_t dma_flag,ddi_dma_attr_t * dma_attr_p,dma_area_t * dma_p)4607956Sxiuyan.wang@Sun.COM unm_alloc_dma_mem(unm_adapter *adapter, int size, uint_t dma_flag,
4617956Sxiuyan.wang@Sun.COM ddi_dma_attr_t *dma_attr_p, dma_area_t *dma_p)
4627956Sxiuyan.wang@Sun.COM {
4637956Sxiuyan.wang@Sun.COM int ret;
4647956Sxiuyan.wang@Sun.COM caddr_t vaddr;
4657956Sxiuyan.wang@Sun.COM size_t actual_size;
4667956Sxiuyan.wang@Sun.COM ddi_dma_cookie_t cookie;
4677956Sxiuyan.wang@Sun.COM
4687956Sxiuyan.wang@Sun.COM ret = ddi_dma_alloc_handle(adapter->dip,
4697956Sxiuyan.wang@Sun.COM dma_attr_p, DDI_DMA_DONTWAIT,
4707956Sxiuyan.wang@Sun.COM NULL, &dma_p->dma_hdl);
4717956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
4727956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: Failed ddi_dma_alloc_handle\n",
4737956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
4747956Sxiuyan.wang@Sun.COM goto dma_mem_fail;
4757956Sxiuyan.wang@Sun.COM }
4767956Sxiuyan.wang@Sun.COM
4777956Sxiuyan.wang@Sun.COM ret = ddi_dma_mem_alloc(dma_p->dma_hdl,
4787956Sxiuyan.wang@Sun.COM size, &adapter->gc_attr_desc,
4797956Sxiuyan.wang@Sun.COM dma_flag & (DDI_DMA_STREAMING | DDI_DMA_CONSISTENT),
4807956Sxiuyan.wang@Sun.COM DDI_DMA_DONTWAIT, NULL, &vaddr, &actual_size,
4817956Sxiuyan.wang@Sun.COM &dma_p->acc_hdl);
4827956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
4837956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: ddi_dma_mem_alloc() failed\n",
4847956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
4857956Sxiuyan.wang@Sun.COM goto dma_mem_fail;
4867956Sxiuyan.wang@Sun.COM }
4877956Sxiuyan.wang@Sun.COM
4887956Sxiuyan.wang@Sun.COM if (actual_size < size) {
4897956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: ddi_dma_mem_alloc() allocated small\n",
4907956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
4917956Sxiuyan.wang@Sun.COM goto dma_mem_fail;
4927956Sxiuyan.wang@Sun.COM }
4937956Sxiuyan.wang@Sun.COM
4947956Sxiuyan.wang@Sun.COM ret = ddi_dma_addr_bind_handle(dma_p->dma_hdl,
4957956Sxiuyan.wang@Sun.COM NULL, vaddr, size, dma_flag, DDI_DMA_DONTWAIT,
4967956Sxiuyan.wang@Sun.COM NULL, &cookie, &dma_p->ncookies);
4977956Sxiuyan.wang@Sun.COM if (ret != DDI_DMA_MAPPED || dma_p->ncookies != 1) {
4987956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: ddi_dma_addr_bind_handle() failed, "
4997956Sxiuyan.wang@Sun.COM "%d, %d\n", adapter->name, adapter->instance, ret,
5007956Sxiuyan.wang@Sun.COM dma_p->ncookies);
5017956Sxiuyan.wang@Sun.COM goto dma_mem_fail;
5027956Sxiuyan.wang@Sun.COM }
5037956Sxiuyan.wang@Sun.COM
5047956Sxiuyan.wang@Sun.COM dma_p->dma_addr = cookie.dmac_laddress;
5057956Sxiuyan.wang@Sun.COM dma_p->vaddr = vaddr;
5067956Sxiuyan.wang@Sun.COM (void) memset(vaddr, 0, size);
5077956Sxiuyan.wang@Sun.COM
5087956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
5097956Sxiuyan.wang@Sun.COM
5107956Sxiuyan.wang@Sun.COM dma_mem_fail:
5117956Sxiuyan.wang@Sun.COM unm_free_dma_mem(dma_p);
5127956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
5137956Sxiuyan.wang@Sun.COM }
5147956Sxiuyan.wang@Sun.COM
515*9436SJing.Xiong@Sun.COM static void
unm_free_tx_buffers(unm_adapter * adapter)5167956Sxiuyan.wang@Sun.COM unm_free_tx_buffers(unm_adapter *adapter)
5177956Sxiuyan.wang@Sun.COM {
5187956Sxiuyan.wang@Sun.COM int i;
5197956Sxiuyan.wang@Sun.COM dma_area_t *dma_p;
5207956Sxiuyan.wang@Sun.COM struct unm_cmd_buffer *cmd_buf;
5217956Sxiuyan.wang@Sun.COM unm_dmah_node_t *nodep;
5227956Sxiuyan.wang@Sun.COM
5237956Sxiuyan.wang@Sun.COM cmd_buf = &adapter->cmd_buf_arr[0];
5247956Sxiuyan.wang@Sun.COM
5257956Sxiuyan.wang@Sun.COM for (i = 0; i < adapter->MaxTxDescCount; i++) {
5267956Sxiuyan.wang@Sun.COM dma_p = &cmd_buf->dma_area;
5277956Sxiuyan.wang@Sun.COM unm_free_dma_mem(dma_p);
5287956Sxiuyan.wang@Sun.COM nodep = cmd_buf->head;
5297956Sxiuyan.wang@Sun.COM while (nodep != NULL) {
5307956Sxiuyan.wang@Sun.COM (void) ddi_dma_unbind_handle(nodep->dmahdl);
5317956Sxiuyan.wang@Sun.COM nodep = nodep->next;
5327956Sxiuyan.wang@Sun.COM }
5337956Sxiuyan.wang@Sun.COM if (cmd_buf->msg != NULL)
5347956Sxiuyan.wang@Sun.COM freemsg(cmd_buf->msg);
5357956Sxiuyan.wang@Sun.COM cmd_buf++;
5367956Sxiuyan.wang@Sun.COM }
5377956Sxiuyan.wang@Sun.COM adapter->freecmds = 0;
5387956Sxiuyan.wang@Sun.COM }
5397956Sxiuyan.wang@Sun.COM
5407956Sxiuyan.wang@Sun.COM static int
unm_alloc_tx_buffers(unm_adapter * adapter)5417956Sxiuyan.wang@Sun.COM unm_alloc_tx_buffers(unm_adapter *adapter)
5427956Sxiuyan.wang@Sun.COM {
5437956Sxiuyan.wang@Sun.COM int i, ret, size, allocated = 0;
5447956Sxiuyan.wang@Sun.COM dma_area_t *dma_p;
5457956Sxiuyan.wang@Sun.COM struct unm_cmd_buffer *cmd_buf;
5467956Sxiuyan.wang@Sun.COM
5477956Sxiuyan.wang@Sun.COM cmd_buf = &adapter->cmd_buf_arr[0];
5487956Sxiuyan.wang@Sun.COM size = adapter->maxmtu;
5497956Sxiuyan.wang@Sun.COM
5507956Sxiuyan.wang@Sun.COM for (i = 0; i < adapter->MaxTxDescCount; i++) {
5517956Sxiuyan.wang@Sun.COM dma_p = &cmd_buf->dma_area;
5527956Sxiuyan.wang@Sun.COM ret = unm_alloc_dma_mem(adapter, size,
5537956Sxiuyan.wang@Sun.COM DDI_DMA_WRITE | DDI_DMA_STREAMING,
5547956Sxiuyan.wang@Sun.COM &unm_dma_attr_rxbuf, dma_p);
5557956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS)
5567956Sxiuyan.wang@Sun.COM goto alloc_tx_buffer_fail;
5577956Sxiuyan.wang@Sun.COM
5587956Sxiuyan.wang@Sun.COM allocated++;
5597956Sxiuyan.wang@Sun.COM cmd_buf++;
5607956Sxiuyan.wang@Sun.COM }
5617956Sxiuyan.wang@Sun.COM adapter->freecmds = adapter->MaxTxDescCount;
5627956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
5637956Sxiuyan.wang@Sun.COM
5647956Sxiuyan.wang@Sun.COM alloc_tx_buffer_fail:
5657956Sxiuyan.wang@Sun.COM
5667956Sxiuyan.wang@Sun.COM cmd_buf = &adapter->cmd_buf_arr[0];
5677956Sxiuyan.wang@Sun.COM for (i = 0; i < allocated; i++) {
5687956Sxiuyan.wang@Sun.COM dma_p = &cmd_buf->dma_area;
5697956Sxiuyan.wang@Sun.COM unm_free_dma_mem(dma_p);
5707956Sxiuyan.wang@Sun.COM cmd_buf++;
5717956Sxiuyan.wang@Sun.COM }
5727956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: Failed transmit ring memory allocation\n",
5737956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
5747956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
5757956Sxiuyan.wang@Sun.COM }
5767956Sxiuyan.wang@Sun.COM
5777956Sxiuyan.wang@Sun.COM /*
5787956Sxiuyan.wang@Sun.COM * Called by freemsg() to "free" the resource.
5797956Sxiuyan.wang@Sun.COM */
5807956Sxiuyan.wang@Sun.COM static void
unm_rx_buffer_recycle(char * arg)5817956Sxiuyan.wang@Sun.COM unm_rx_buffer_recycle(char *arg)
5827956Sxiuyan.wang@Sun.COM {
5837956Sxiuyan.wang@Sun.COM unm_rx_buffer_t *rx_buffer = (unm_rx_buffer_t *)(uintptr_t)arg;
5847956Sxiuyan.wang@Sun.COM unm_adapter *adapter = rx_buffer->adapter;
5857956Sxiuyan.wang@Sun.COM unm_rcv_desc_ctx_t *rcv_desc = rx_buffer->rcv_desc;
5867956Sxiuyan.wang@Sun.COM
5877956Sxiuyan.wang@Sun.COM rx_buffer->mp = desballoc(rx_buffer->dma_info.vaddr,
5887956Sxiuyan.wang@Sun.COM rcv_desc->dma_size, 0, &rx_buffer->rx_recycle);
5897956Sxiuyan.wang@Sun.COM
5907956Sxiuyan.wang@Sun.COM if (rx_buffer->mp == NULL)
5917956Sxiuyan.wang@Sun.COM adapter->stats.desballocfailed++;
5927956Sxiuyan.wang@Sun.COM
5937956Sxiuyan.wang@Sun.COM mutex_enter(rcv_desc->recycle_lock);
5947956Sxiuyan.wang@Sun.COM rx_buffer->next = rcv_desc->recycle_list;
5957956Sxiuyan.wang@Sun.COM rcv_desc->recycle_list = rx_buffer;
5967956Sxiuyan.wang@Sun.COM rcv_desc->rx_buf_recycle++;
5977956Sxiuyan.wang@Sun.COM mutex_exit(rcv_desc->recycle_lock);
5987956Sxiuyan.wang@Sun.COM }
5997956Sxiuyan.wang@Sun.COM
600*9436SJing.Xiong@Sun.COM static void
unm_destroy_rx_ring(unm_rcv_desc_ctx_t * rcv_desc)6017956Sxiuyan.wang@Sun.COM unm_destroy_rx_ring(unm_rcv_desc_ctx_t *rcv_desc)
6027956Sxiuyan.wang@Sun.COM {
6037956Sxiuyan.wang@Sun.COM uint32_t i, total_buf;
6047956Sxiuyan.wang@Sun.COM unm_rx_buffer_t *buf_pool;
6057956Sxiuyan.wang@Sun.COM
6067956Sxiuyan.wang@Sun.COM total_buf = rcv_desc->rx_buf_total;
6077956Sxiuyan.wang@Sun.COM buf_pool = rcv_desc->rx_buf_pool;
6087956Sxiuyan.wang@Sun.COM for (i = 0; i < total_buf; i++) {
6097956Sxiuyan.wang@Sun.COM if (buf_pool->mp != NULL)
6107956Sxiuyan.wang@Sun.COM freemsg(buf_pool->mp);
6117956Sxiuyan.wang@Sun.COM unm_free_dma_mem(&buf_pool->dma_info);
6127956Sxiuyan.wang@Sun.COM buf_pool++;
6137956Sxiuyan.wang@Sun.COM }
6147956Sxiuyan.wang@Sun.COM
6157956Sxiuyan.wang@Sun.COM kmem_free(rcv_desc->rx_buf_pool, sizeof (unm_rx_buffer_t) * total_buf);
6167956Sxiuyan.wang@Sun.COM rcv_desc->rx_buf_pool = NULL;
6177956Sxiuyan.wang@Sun.COM rcv_desc->pool_list = NULL;
6187956Sxiuyan.wang@Sun.COM rcv_desc->recycle_list = NULL;
6197956Sxiuyan.wang@Sun.COM rcv_desc->rx_buf_free = 0;
6207956Sxiuyan.wang@Sun.COM
6217956Sxiuyan.wang@Sun.COM mutex_destroy(rcv_desc->pool_lock);
6227956Sxiuyan.wang@Sun.COM mutex_destroy(rcv_desc->recycle_lock);
6237956Sxiuyan.wang@Sun.COM }
6247956Sxiuyan.wang@Sun.COM
6257956Sxiuyan.wang@Sun.COM static int
unm_create_rx_ring(unm_adapter * adapter,unm_rcv_desc_ctx_t * rcv_desc)6267956Sxiuyan.wang@Sun.COM unm_create_rx_ring(unm_adapter *adapter, unm_rcv_desc_ctx_t *rcv_desc)
6277956Sxiuyan.wang@Sun.COM {
6287956Sxiuyan.wang@Sun.COM int i, ret, allocate = 0, sreoff;
6297956Sxiuyan.wang@Sun.COM uint32_t total_buf;
6307956Sxiuyan.wang@Sun.COM dma_area_t *dma_info;
6317956Sxiuyan.wang@Sun.COM unm_rx_buffer_t *rx_buffer;
6327956Sxiuyan.wang@Sun.COM
6337956Sxiuyan.wang@Sun.COM sreoff = adapter->ahw.cut_through ? 0 : IP_ALIGNMENT_BYTES;
6347956Sxiuyan.wang@Sun.COM
6357956Sxiuyan.wang@Sun.COM /* temporarily set the total rx buffers two times of MaxRxDescCount */
6367956Sxiuyan.wang@Sun.COM total_buf = rcv_desc->rx_buf_total = rcv_desc->MaxRxDescCount * 2;
6377956Sxiuyan.wang@Sun.COM
6387956Sxiuyan.wang@Sun.COM rcv_desc->rx_buf_pool = kmem_zalloc(sizeof (unm_rx_buffer_t) *
6397956Sxiuyan.wang@Sun.COM total_buf, KM_SLEEP);
6407956Sxiuyan.wang@Sun.COM rx_buffer = rcv_desc->rx_buf_pool;
6417956Sxiuyan.wang@Sun.COM for (i = 0; i < total_buf; i++) {
6427956Sxiuyan.wang@Sun.COM dma_info = &rx_buffer->dma_info;
6437956Sxiuyan.wang@Sun.COM ret = unm_alloc_dma_mem(adapter, rcv_desc->buf_size,
6447956Sxiuyan.wang@Sun.COM DDI_DMA_READ | DDI_DMA_STREAMING,
6457956Sxiuyan.wang@Sun.COM &unm_dma_attr_rxbuf, dma_info);
6467956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS)
6477956Sxiuyan.wang@Sun.COM goto alloc_mem_failed;
6487956Sxiuyan.wang@Sun.COM else {
6497956Sxiuyan.wang@Sun.COM allocate++;
6507956Sxiuyan.wang@Sun.COM dma_info->vaddr = (void *) ((char *)dma_info->vaddr +
6517956Sxiuyan.wang@Sun.COM sreoff);
6527956Sxiuyan.wang@Sun.COM dma_info->dma_addr += sreoff;
6537956Sxiuyan.wang@Sun.COM rx_buffer->rx_recycle.free_func =
6547956Sxiuyan.wang@Sun.COM unm_rx_buffer_recycle;
6557956Sxiuyan.wang@Sun.COM rx_buffer->rx_recycle.free_arg = (caddr_t)rx_buffer;
6567956Sxiuyan.wang@Sun.COM rx_buffer->next = NULL;
6577956Sxiuyan.wang@Sun.COM rx_buffer->mp = desballoc(dma_info->vaddr,
6587956Sxiuyan.wang@Sun.COM rcv_desc->dma_size, 0, &rx_buffer->rx_recycle);
6597956Sxiuyan.wang@Sun.COM if (rx_buffer->mp == NULL)
6607956Sxiuyan.wang@Sun.COM adapter->stats.desballocfailed++;
6617956Sxiuyan.wang@Sun.COM rx_buffer->rcv_desc = rcv_desc;
6627956Sxiuyan.wang@Sun.COM rx_buffer->adapter = adapter;
6637956Sxiuyan.wang@Sun.COM rx_buffer++;
6647956Sxiuyan.wang@Sun.COM }
6657956Sxiuyan.wang@Sun.COM }
6667956Sxiuyan.wang@Sun.COM
6677956Sxiuyan.wang@Sun.COM for (i = 0; i < (total_buf - 1); i++) {
6687956Sxiuyan.wang@Sun.COM rcv_desc->rx_buf_pool[i].next = &rcv_desc->rx_buf_pool[i + 1];
6697956Sxiuyan.wang@Sun.COM }
6707956Sxiuyan.wang@Sun.COM
6717956Sxiuyan.wang@Sun.COM rcv_desc->pool_list = rcv_desc->rx_buf_pool;
6727956Sxiuyan.wang@Sun.COM rcv_desc->recycle_list = NULL;
6737956Sxiuyan.wang@Sun.COM rcv_desc->rx_buf_free = total_buf;
6747956Sxiuyan.wang@Sun.COM
6757956Sxiuyan.wang@Sun.COM mutex_init(rcv_desc->pool_lock, NULL,
6767956Sxiuyan.wang@Sun.COM MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
6777956Sxiuyan.wang@Sun.COM mutex_init(rcv_desc->recycle_lock, NULL,
6787956Sxiuyan.wang@Sun.COM MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
6797956Sxiuyan.wang@Sun.COM
6807956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
6817956Sxiuyan.wang@Sun.COM
6827956Sxiuyan.wang@Sun.COM alloc_mem_failed:
6837956Sxiuyan.wang@Sun.COM rx_buffer = rcv_desc->rx_buf_pool;
6847956Sxiuyan.wang@Sun.COM for (i = 0; i < allocate; i++, rx_buffer++) {
6857956Sxiuyan.wang@Sun.COM dma_info = &rx_buffer->dma_info;
6867956Sxiuyan.wang@Sun.COM if (rx_buffer->mp != NULL)
6877956Sxiuyan.wang@Sun.COM freemsg(rx_buffer->mp);
6887956Sxiuyan.wang@Sun.COM unm_free_dma_mem(dma_info);
6897956Sxiuyan.wang@Sun.COM }
6907956Sxiuyan.wang@Sun.COM
6917956Sxiuyan.wang@Sun.COM kmem_free(rcv_desc->rx_buf_pool, sizeof (unm_rx_buffer_t) * total_buf);
6927956Sxiuyan.wang@Sun.COM rcv_desc->rx_buf_pool = NULL;
6937956Sxiuyan.wang@Sun.COM
6947956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: Failed receive ring resource allocation\n",
6957956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
6967956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
6977956Sxiuyan.wang@Sun.COM }
6987956Sxiuyan.wang@Sun.COM
6997956Sxiuyan.wang@Sun.COM static void
unm_check_options(unm_adapter * adapter)7007956Sxiuyan.wang@Sun.COM unm_check_options(unm_adapter *adapter)
7017956Sxiuyan.wang@Sun.COM {
702*9436SJing.Xiong@Sun.COM int i, ring, tx_desc, rx_desc, rx_jdesc, maxrx;
7037956Sxiuyan.wang@Sun.COM unm_recv_context_t *recv_ctx;
7047956Sxiuyan.wang@Sun.COM unm_rcv_desc_ctx_t *rcv_desc;
7057956Sxiuyan.wang@Sun.COM uint8_t revid = adapter->ahw.revision_id;
7067956Sxiuyan.wang@Sun.COM dev_info_t *dip = adapter->dip;
7077956Sxiuyan.wang@Sun.COM
708*9436SJing.Xiong@Sun.COM /*
709*9436SJing.Xiong@Sun.COM * Reduce number of regular rcv desc to half on x86.
710*9436SJing.Xiong@Sun.COM */
711*9436SJing.Xiong@Sun.COM maxrx = MAX_RCV_DESCRIPTORS;
712*9436SJing.Xiong@Sun.COM #if !defined(_LP64)
713*9436SJing.Xiong@Sun.COM maxrx /= 2;
714*9436SJing.Xiong@Sun.COM #endif /* !_LP64 */
715*9436SJing.Xiong@Sun.COM
7167956Sxiuyan.wang@Sun.COM verbmsg = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
7177956Sxiuyan.wang@Sun.COM dmesg_propname, 0);
7187956Sxiuyan.wang@Sun.COM
7197956Sxiuyan.wang@Sun.COM adapter->tx_bcopy_threshold = ddi_prop_get_int(DDI_DEV_T_ANY,
7207956Sxiuyan.wang@Sun.COM dip, DDI_PROP_DONTPASS, txbcopythreshold_propname,
7217956Sxiuyan.wang@Sun.COM UNM_TX_BCOPY_THRESHOLD);
7227956Sxiuyan.wang@Sun.COM adapter->rx_bcopy_threshold = ddi_prop_get_int(DDI_DEV_T_ANY,
7237956Sxiuyan.wang@Sun.COM dip, DDI_PROP_DONTPASS, rxbcopythreshold_propname,
7247956Sxiuyan.wang@Sun.COM UNM_RX_BCOPY_THRESHOLD);
7257956Sxiuyan.wang@Sun.COM
7267956Sxiuyan.wang@Sun.COM tx_desc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
7277956Sxiuyan.wang@Sun.COM txringsize_propname, MAX_CMD_DESCRIPTORS_HOST);
7287956Sxiuyan.wang@Sun.COM if (tx_desc >= 256 && tx_desc <= MAX_CMD_DESCRIPTORS &&
7297956Sxiuyan.wang@Sun.COM !(tx_desc & (tx_desc - 1))) {
7307956Sxiuyan.wang@Sun.COM adapter->MaxTxDescCount = tx_desc;
7317956Sxiuyan.wang@Sun.COM } else {
7327956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: TxRingSize defaulting to %d, since "
7337956Sxiuyan.wang@Sun.COM ".conf value is not 2 power aligned in range 256 - %d\n",
7347956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance, MAX_CMD_DESCRIPTORS_HOST,
7357956Sxiuyan.wang@Sun.COM MAX_CMD_DESCRIPTORS);
7367956Sxiuyan.wang@Sun.COM adapter->MaxTxDescCount = MAX_CMD_DESCRIPTORS_HOST;
7377956Sxiuyan.wang@Sun.COM }
7387956Sxiuyan.wang@Sun.COM
7397956Sxiuyan.wang@Sun.COM rx_desc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
740*9436SJing.Xiong@Sun.COM rxringsize_propname, maxrx);
7417956Sxiuyan.wang@Sun.COM if (rx_desc >= NX_MIN_DRIVER_RDS_SIZE &&
7427956Sxiuyan.wang@Sun.COM rx_desc <= NX_MAX_SUPPORTED_RDS_SIZE &&
7437956Sxiuyan.wang@Sun.COM !(rx_desc & (rx_desc - 1))) {
7447956Sxiuyan.wang@Sun.COM adapter->MaxRxDescCount = rx_desc;
7457956Sxiuyan.wang@Sun.COM } else {
7467956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: RxRingSize defaulting to %d, since "
7477956Sxiuyan.wang@Sun.COM ".conf value is not 2 power aligned in range %d - %d\n",
7487956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance, MAX_RCV_DESCRIPTORS,
7497956Sxiuyan.wang@Sun.COM NX_MIN_DRIVER_RDS_SIZE, NX_MAX_SUPPORTED_RDS_SIZE);
7507956Sxiuyan.wang@Sun.COM adapter->MaxRxDescCount = MAX_RCV_DESCRIPTORS;
7517956Sxiuyan.wang@Sun.COM }
7527956Sxiuyan.wang@Sun.COM
7537956Sxiuyan.wang@Sun.COM rx_jdesc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
7547956Sxiuyan.wang@Sun.COM jumborxringsize_propname, MAX_JUMBO_RCV_DESCRIPTORS);
7557956Sxiuyan.wang@Sun.COM if (rx_jdesc >= NX_MIN_DRIVER_RDS_SIZE &&
7567956Sxiuyan.wang@Sun.COM rx_jdesc <= NX_MAX_SUPPORTED_JUMBO_RDS_SIZE &&
7577956Sxiuyan.wang@Sun.COM !(rx_jdesc & (rx_jdesc - 1))) {
7587956Sxiuyan.wang@Sun.COM adapter->MaxJumboRxDescCount = rx_jdesc;
7597956Sxiuyan.wang@Sun.COM } else {
7607956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: JumboRingSize defaulting to %d, since "
7617956Sxiuyan.wang@Sun.COM ".conf value is not 2 power aligned in range %d - %d\n",
7627956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance, MAX_JUMBO_RCV_DESCRIPTORS,
7637956Sxiuyan.wang@Sun.COM NX_MIN_DRIVER_RDS_SIZE, NX_MAX_SUPPORTED_JUMBO_RDS_SIZE);
7647956Sxiuyan.wang@Sun.COM adapter->MaxJumboRxDescCount = MAX_JUMBO_RCV_DESCRIPTORS;
7657956Sxiuyan.wang@Sun.COM }
7667956Sxiuyan.wang@Sun.COM
767*9436SJing.Xiong@Sun.COM /*
768*9436SJing.Xiong@Sun.COM * Solaris does not use LRO, but older firmware needs to have a
769*9436SJing.Xiong@Sun.COM * couple of descriptors for initialization.
770*9436SJing.Xiong@Sun.COM */
771*9436SJing.Xiong@Sun.COM adapter->MaxLroRxDescCount = (adapter->fw_major < 4) ? 2 : 0;
7727956Sxiuyan.wang@Sun.COM
7737956Sxiuyan.wang@Sun.COM adapter->mtu = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
7747956Sxiuyan.wang@Sun.COM DDI_PROP_DONTPASS, defaultmtu_propname, MTU_SIZE);
7757956Sxiuyan.wang@Sun.COM
7767956Sxiuyan.wang@Sun.COM if (adapter->mtu < MTU_SIZE) {
7777956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "Raising mtu to %d\n", MTU_SIZE);
7787956Sxiuyan.wang@Sun.COM adapter->mtu = MTU_SIZE;
7797956Sxiuyan.wang@Sun.COM }
7807956Sxiuyan.wang@Sun.COM adapter->maxmtu = NX_IS_REVISION_P2(revid) ? P2_MAX_MTU : P3_MAX_MTU;
7817956Sxiuyan.wang@Sun.COM if (adapter->mtu > adapter->maxmtu) {
7827956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "Lowering mtu to %d\n", adapter->maxmtu);
7837956Sxiuyan.wang@Sun.COM adapter->mtu = adapter->maxmtu;
7847956Sxiuyan.wang@Sun.COM }
7857956Sxiuyan.wang@Sun.COM
786*9436SJing.Xiong@Sun.COM adapter->maxmtu = adapter->mtu + NX_MAX_ETHERHDR;
787*9436SJing.Xiong@Sun.COM
788*9436SJing.Xiong@Sun.COM /*
789*9436SJing.Xiong@Sun.COM * If we are not expecting to receive jumbo frames, save memory and
790*9436SJing.Xiong@Sun.COM * do not allocate.
791*9436SJing.Xiong@Sun.COM */
792*9436SJing.Xiong@Sun.COM if (adapter->mtu <= MTU_SIZE)
793*9436SJing.Xiong@Sun.COM adapter->MaxJumboRxDescCount = NX_MIN_DRIVER_RDS_SIZE;
7947956Sxiuyan.wang@Sun.COM
7957956Sxiuyan.wang@Sun.COM for (i = 0; i < MAX_RCV_CTX; ++i) {
7967956Sxiuyan.wang@Sun.COM recv_ctx = &adapter->recv_ctx[i];
7977956Sxiuyan.wang@Sun.COM
7987956Sxiuyan.wang@Sun.COM for (ring = 0; ring < adapter->max_rds_rings; ring++) {
7997956Sxiuyan.wang@Sun.COM rcv_desc = &recv_ctx->rcv_desc[ring];
8007956Sxiuyan.wang@Sun.COM
8017956Sxiuyan.wang@Sun.COM switch (RCV_DESC_TYPE(ring)) {
8027956Sxiuyan.wang@Sun.COM case RCV_DESC_NORMAL:
8037956Sxiuyan.wang@Sun.COM rcv_desc->MaxRxDescCount =
8047956Sxiuyan.wang@Sun.COM adapter->MaxRxDescCount;
8057956Sxiuyan.wang@Sun.COM if (adapter->ahw.cut_through) {
8067956Sxiuyan.wang@Sun.COM rcv_desc->dma_size =
8077956Sxiuyan.wang@Sun.COM NX_CT_DEFAULT_RX_BUF_LEN;
8087956Sxiuyan.wang@Sun.COM rcv_desc->buf_size = rcv_desc->dma_size;
8097956Sxiuyan.wang@Sun.COM } else {
8107956Sxiuyan.wang@Sun.COM rcv_desc->dma_size =
8117956Sxiuyan.wang@Sun.COM NX_RX_NORMAL_BUF_MAX_LEN;
8127956Sxiuyan.wang@Sun.COM rcv_desc->buf_size =
8137956Sxiuyan.wang@Sun.COM rcv_desc->dma_size +
8147956Sxiuyan.wang@Sun.COM IP_ALIGNMENT_BYTES;
8157956Sxiuyan.wang@Sun.COM }
8167956Sxiuyan.wang@Sun.COM break;
8177956Sxiuyan.wang@Sun.COM
8187956Sxiuyan.wang@Sun.COM case RCV_DESC_JUMBO:
8197956Sxiuyan.wang@Sun.COM rcv_desc->MaxRxDescCount =
8207956Sxiuyan.wang@Sun.COM adapter->MaxJumboRxDescCount;
8217956Sxiuyan.wang@Sun.COM if (adapter->ahw.cut_through) {
8227956Sxiuyan.wang@Sun.COM rcv_desc->dma_size =
8237956Sxiuyan.wang@Sun.COM rcv_desc->buf_size =
8247956Sxiuyan.wang@Sun.COM NX_P3_RX_JUMBO_BUF_MAX_LEN;
8257956Sxiuyan.wang@Sun.COM } else {
8267956Sxiuyan.wang@Sun.COM if (NX_IS_REVISION_P2(revid))
8277956Sxiuyan.wang@Sun.COM rcv_desc->dma_size =
8287956Sxiuyan.wang@Sun.COM NX_P2_RX_JUMBO_BUF_MAX_LEN;
8297956Sxiuyan.wang@Sun.COM else
8307956Sxiuyan.wang@Sun.COM rcv_desc->dma_size =
8317956Sxiuyan.wang@Sun.COM NX_P3_RX_JUMBO_BUF_MAX_LEN;
8327956Sxiuyan.wang@Sun.COM rcv_desc->buf_size =
8337956Sxiuyan.wang@Sun.COM rcv_desc->dma_size +
8347956Sxiuyan.wang@Sun.COM IP_ALIGNMENT_BYTES;
8357956Sxiuyan.wang@Sun.COM }
8367956Sxiuyan.wang@Sun.COM break;
8377956Sxiuyan.wang@Sun.COM
8387956Sxiuyan.wang@Sun.COM case RCV_RING_LRO:
8397956Sxiuyan.wang@Sun.COM rcv_desc->MaxRxDescCount =
8407956Sxiuyan.wang@Sun.COM adapter->MaxLroRxDescCount;
8417956Sxiuyan.wang@Sun.COM rcv_desc->buf_size = MAX_RX_LRO_BUFFER_LENGTH;
8427956Sxiuyan.wang@Sun.COM rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN;
8437956Sxiuyan.wang@Sun.COM break;
8447956Sxiuyan.wang@Sun.COM default:
8457956Sxiuyan.wang@Sun.COM break;
8467956Sxiuyan.wang@Sun.COM }
8477956Sxiuyan.wang@Sun.COM }
8487956Sxiuyan.wang@Sun.COM }
8497956Sxiuyan.wang@Sun.COM }
8507956Sxiuyan.wang@Sun.COM
8517956Sxiuyan.wang@Sun.COM static void
vector128M(unm_adapter * aptr)8527956Sxiuyan.wang@Sun.COM vector128M(unm_adapter *aptr)
8537956Sxiuyan.wang@Sun.COM {
8547956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_change_crbwindow = &unm_nic_pci_change_crbwindow_128M;
8557956Sxiuyan.wang@Sun.COM aptr->unm_crb_writelit_adapter = &unm_crb_writelit_adapter_128M;
8567956Sxiuyan.wang@Sun.COM aptr->unm_nic_hw_write_wx = &unm_nic_hw_write_wx_128M;
8577956Sxiuyan.wang@Sun.COM aptr->unm_nic_hw_read_wx = &unm_nic_hw_read_wx_128M;
8587956Sxiuyan.wang@Sun.COM aptr->unm_nic_hw_write_ioctl = &unm_nic_hw_write_ioctl_128M;
8597956Sxiuyan.wang@Sun.COM aptr->unm_nic_hw_read_ioctl = &unm_nic_hw_read_ioctl_128M;
8607956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_mem_write = &unm_nic_pci_mem_write_128M;
8617956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_mem_read = &unm_nic_pci_mem_read_128M;
8627956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_write_immediate = &unm_nic_pci_write_immediate_128M;
8637956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_read_immediate = &unm_nic_pci_read_immediate_128M;
8647956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_write_normalize = &unm_nic_pci_write_normalize_128M;
8657956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_read_normalize = &unm_nic_pci_read_normalize_128M;
8667956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_set_window = &unm_nic_pci_set_window_128M;
8677956Sxiuyan.wang@Sun.COM aptr->unm_nic_clear_statistics = &unm_nic_clear_statistics_128M;
8687956Sxiuyan.wang@Sun.COM aptr->unm_nic_fill_statistics = &unm_nic_fill_statistics_128M;
8697956Sxiuyan.wang@Sun.COM }
8707956Sxiuyan.wang@Sun.COM
8717956Sxiuyan.wang@Sun.COM static void
vector2M(unm_adapter * aptr)8727956Sxiuyan.wang@Sun.COM vector2M(unm_adapter *aptr)
8737956Sxiuyan.wang@Sun.COM {
8747956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_change_crbwindow = &unm_nic_pci_change_crbwindow_2M;
8757956Sxiuyan.wang@Sun.COM aptr->unm_crb_writelit_adapter = &unm_crb_writelit_adapter_2M;
8767956Sxiuyan.wang@Sun.COM aptr->unm_nic_hw_write_wx = &unm_nic_hw_write_wx_2M;
8777956Sxiuyan.wang@Sun.COM aptr->unm_nic_hw_read_wx = &unm_nic_hw_read_wx_2M;
8787956Sxiuyan.wang@Sun.COM aptr->unm_nic_hw_write_ioctl = &unm_nic_hw_write_wx_2M;
8797956Sxiuyan.wang@Sun.COM aptr->unm_nic_hw_read_ioctl = &unm_nic_hw_read_wx_2M;
8807956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_mem_write = &unm_nic_pci_mem_write_2M;
8817956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_mem_read = &unm_nic_pci_mem_read_2M;
8827956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_write_immediate = &unm_nic_pci_write_immediate_2M;
8837956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_read_immediate = &unm_nic_pci_read_immediate_2M;
8847956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_write_normalize = &unm_nic_pci_write_normalize_2M;
8857956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_read_normalize = &unm_nic_pci_read_normalize_2M;
8867956Sxiuyan.wang@Sun.COM aptr->unm_nic_pci_set_window = &unm_nic_pci_set_window_2M;
8877956Sxiuyan.wang@Sun.COM aptr->unm_nic_clear_statistics = &unm_nic_clear_statistics_2M;
8887956Sxiuyan.wang@Sun.COM aptr->unm_nic_fill_statistics = &unm_nic_fill_statistics_2M;
8897956Sxiuyan.wang@Sun.COM }
8907956Sxiuyan.wang@Sun.COM
8917956Sxiuyan.wang@Sun.COM static int
unm_pci_map_setup(unm_adapter * adapter)8927956Sxiuyan.wang@Sun.COM unm_pci_map_setup(unm_adapter *adapter)
8937956Sxiuyan.wang@Sun.COM {
8947956Sxiuyan.wang@Sun.COM int ret;
8957956Sxiuyan.wang@Sun.COM caddr_t reg_base, db_base;
8967956Sxiuyan.wang@Sun.COM caddr_t mem_ptr0, mem_ptr1 = NULL, mem_ptr2 = NULL;
8977956Sxiuyan.wang@Sun.COM unsigned long pci_len0;
8987956Sxiuyan.wang@Sun.COM unsigned long first_page_group_start, first_page_group_end;
8997956Sxiuyan.wang@Sun.COM
9007956Sxiuyan.wang@Sun.COM off_t regsize, dbsize = UNM_DB_MAPSIZE_BYTES;
9017956Sxiuyan.wang@Sun.COM dev_info_t *dip = adapter->dip;
9027956Sxiuyan.wang@Sun.COM
9037956Sxiuyan.wang@Sun.COM adapter->ahw.qdr_sn_window = adapter->ahw.ddr_mn_window = -1;
9047956Sxiuyan.wang@Sun.COM
9057956Sxiuyan.wang@Sun.COM /* map register space */
9067956Sxiuyan.wang@Sun.COM
9077956Sxiuyan.wang@Sun.COM ret = ddi_dev_regsize(dip, 1, ®size);
9087956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
9097956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: failed to read reg size for bar0\n",
9107956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
9117956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
9127956Sxiuyan.wang@Sun.COM }
9137956Sxiuyan.wang@Sun.COM
9147956Sxiuyan.wang@Sun.COM ret = ddi_regs_map_setup(dip, 1, ®_base, 0,
9157956Sxiuyan.wang@Sun.COM regsize, &unm_dev_attr, &adapter->regs_handle);
9167956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
9177956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: failed to map registers\n",
9187956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
9197956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
9207956Sxiuyan.wang@Sun.COM }
9217956Sxiuyan.wang@Sun.COM
9227956Sxiuyan.wang@Sun.COM mem_ptr0 = reg_base;
9237956Sxiuyan.wang@Sun.COM
9247956Sxiuyan.wang@Sun.COM if (regsize == UNM_PCI_128MB_SIZE) {
9257956Sxiuyan.wang@Sun.COM pci_len0 = FIRST_PAGE_GROUP_SIZE;
9267956Sxiuyan.wang@Sun.COM mem_ptr1 = mem_ptr0 + SECOND_PAGE_GROUP_START;
9277956Sxiuyan.wang@Sun.COM mem_ptr2 = mem_ptr0 + THIRD_PAGE_GROUP_START;
9287956Sxiuyan.wang@Sun.COM first_page_group_start = FIRST_PAGE_GROUP_START;
9297956Sxiuyan.wang@Sun.COM first_page_group_end = FIRST_PAGE_GROUP_END;
9307956Sxiuyan.wang@Sun.COM vector128M(adapter);
9317956Sxiuyan.wang@Sun.COM } else if (regsize == UNM_PCI_32MB_SIZE) {
9327956Sxiuyan.wang@Sun.COM pci_len0 = 0;
9337956Sxiuyan.wang@Sun.COM mem_ptr1 = mem_ptr0;
9347956Sxiuyan.wang@Sun.COM mem_ptr2 = mem_ptr0 +
9357956Sxiuyan.wang@Sun.COM (THIRD_PAGE_GROUP_START - SECOND_PAGE_GROUP_START);
9367956Sxiuyan.wang@Sun.COM first_page_group_start = 0;
9377956Sxiuyan.wang@Sun.COM first_page_group_end = 0;
9387956Sxiuyan.wang@Sun.COM vector128M(adapter);
9397956Sxiuyan.wang@Sun.COM } else if (regsize == UNM_PCI_2MB_SIZE) {
9407956Sxiuyan.wang@Sun.COM pci_len0 = UNM_PCI_2MB_SIZE;
9417956Sxiuyan.wang@Sun.COM first_page_group_start = 0;
9427956Sxiuyan.wang@Sun.COM first_page_group_end = 0;
9437956Sxiuyan.wang@Sun.COM adapter->ahw.ddr_mn_window = adapter->ahw.qdr_sn_window = 0;
9447956Sxiuyan.wang@Sun.COM adapter->ahw.mn_win_crb = 0x100000 + PCIX_MN_WINDOW +
9457956Sxiuyan.wang@Sun.COM (adapter->ahw.pci_func * 0x20);
9467956Sxiuyan.wang@Sun.COM if (adapter->ahw.pci_func < 4)
9477956Sxiuyan.wang@Sun.COM adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW +
9487956Sxiuyan.wang@Sun.COM (adapter->ahw.pci_func * 0x20);
9497956Sxiuyan.wang@Sun.COM else
9507956Sxiuyan.wang@Sun.COM adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW +
9517956Sxiuyan.wang@Sun.COM 0xA0 + ((adapter->ahw.pci_func - 4) * 0x10);
9527956Sxiuyan.wang@Sun.COM vector2M(adapter);
9537956Sxiuyan.wang@Sun.COM } else {
9547956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: invalid pci regs map size %ld\n",
9557956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance, regsize);
9567956Sxiuyan.wang@Sun.COM ddi_regs_map_free(&adapter->regs_handle);
9577956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
9587956Sxiuyan.wang@Sun.COM }
9597956Sxiuyan.wang@Sun.COM
9607956Sxiuyan.wang@Sun.COM adapter->ahw.pci_base0 = (unsigned long)mem_ptr0;
9617956Sxiuyan.wang@Sun.COM adapter->ahw.pci_len0 = pci_len0;
9627956Sxiuyan.wang@Sun.COM adapter->ahw.pci_base1 = (unsigned long)mem_ptr1;
9637956Sxiuyan.wang@Sun.COM adapter->ahw.pci_len1 = SECOND_PAGE_GROUP_SIZE;
9647956Sxiuyan.wang@Sun.COM adapter->ahw.pci_base2 = (unsigned long)mem_ptr2;
9657956Sxiuyan.wang@Sun.COM adapter->ahw.pci_len2 = THIRD_PAGE_GROUP_SIZE;
9667956Sxiuyan.wang@Sun.COM adapter->ahw.crb_base =
9677956Sxiuyan.wang@Sun.COM PCI_OFFSET_SECOND_RANGE(adapter, UNM_PCI_CRBSPACE);
9687956Sxiuyan.wang@Sun.COM
9697956Sxiuyan.wang@Sun.COM adapter->ahw.first_page_group_start = first_page_group_start;
9707956Sxiuyan.wang@Sun.COM adapter->ahw.first_page_group_end = first_page_group_end;
9717956Sxiuyan.wang@Sun.COM
9727956Sxiuyan.wang@Sun.COM /* map doorbell */
9737956Sxiuyan.wang@Sun.COM
9747956Sxiuyan.wang@Sun.COM ret = ddi_regs_map_setup(dip, 2, &db_base, 0,
9757956Sxiuyan.wang@Sun.COM dbsize, &unm_dev_attr, &adapter->db_handle);
9767956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
9777956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: failed to map doorbell\n",
9787956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
9797956Sxiuyan.wang@Sun.COM ddi_regs_map_free(&adapter->regs_handle);
9807956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
9817956Sxiuyan.wang@Sun.COM }
9827956Sxiuyan.wang@Sun.COM
9837956Sxiuyan.wang@Sun.COM adapter->ahw.db_base = (unsigned long)db_base;
9847956Sxiuyan.wang@Sun.COM adapter->ahw.db_len = dbsize;
9857956Sxiuyan.wang@Sun.COM
9867956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
9877956Sxiuyan.wang@Sun.COM }
9887956Sxiuyan.wang@Sun.COM
9897956Sxiuyan.wang@Sun.COM static int
unm_initialize_intr(unm_adapter * adapter)9907956Sxiuyan.wang@Sun.COM unm_initialize_intr(unm_adapter *adapter)
9917956Sxiuyan.wang@Sun.COM {
9927956Sxiuyan.wang@Sun.COM
9937956Sxiuyan.wang@Sun.COM int ret;
9947956Sxiuyan.wang@Sun.COM int type, count, avail, actual;
9957956Sxiuyan.wang@Sun.COM
9967956Sxiuyan.wang@Sun.COM ret = ddi_intr_get_supported_types(adapter->dip, &type);
9977956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
9987956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: ddi_intr_get_supported_types() "
9997956Sxiuyan.wang@Sun.COM "failed\n", adapter->name, adapter->instance);
10007956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
10017956Sxiuyan.wang@Sun.COM }
10027956Sxiuyan.wang@Sun.COM
10037956Sxiuyan.wang@Sun.COM type = DDI_INTR_TYPE_MSI;
10047956Sxiuyan.wang@Sun.COM ret = ddi_intr_get_nintrs(adapter->dip, type, &count);
10057956Sxiuyan.wang@Sun.COM if ((ret == DDI_SUCCESS) && (count > 0))
10067956Sxiuyan.wang@Sun.COM goto found_msi;
10077956Sxiuyan.wang@Sun.COM
10087956Sxiuyan.wang@Sun.COM type = DDI_INTR_TYPE_FIXED;
10097956Sxiuyan.wang@Sun.COM ret = ddi_intr_get_nintrs(adapter->dip, type, &count);
10107956Sxiuyan.wang@Sun.COM if ((ret != DDI_SUCCESS) || (count == 0)) {
10117956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN,
10127956Sxiuyan.wang@Sun.COM "ddi_intr_get_nintrs() failure ret=%d\n", ret);
10137956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
10147956Sxiuyan.wang@Sun.COM }
10157956Sxiuyan.wang@Sun.COM
10167956Sxiuyan.wang@Sun.COM found_msi:
10177956Sxiuyan.wang@Sun.COM adapter->intr_type = type;
10187956Sxiuyan.wang@Sun.COM adapter->flags &= ~(UNM_NIC_MSI_ENABLED | UNM_NIC_MSIX_ENABLED);
10197956Sxiuyan.wang@Sun.COM if (type == DDI_INTR_TYPE_MSI)
10207956Sxiuyan.wang@Sun.COM adapter->flags |= UNM_NIC_MSI_ENABLED;
10217956Sxiuyan.wang@Sun.COM
10227956Sxiuyan.wang@Sun.COM /* Get number of available interrupts */
10237956Sxiuyan.wang@Sun.COM ret = ddi_intr_get_navail(adapter->dip, type, &avail);
10247956Sxiuyan.wang@Sun.COM if ((ret != DDI_SUCCESS) || (avail == 0)) {
10257956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "ddi_intr_get_navail() failure, ret=%d\n",
10267956Sxiuyan.wang@Sun.COM ret);
10277956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
10287956Sxiuyan.wang@Sun.COM }
10297956Sxiuyan.wang@Sun.COM
10307956Sxiuyan.wang@Sun.COM ret = ddi_intr_alloc(adapter->dip, &adapter->intr_handle,
10317956Sxiuyan.wang@Sun.COM type, 0, 1, &actual, DDI_INTR_ALLOC_NORMAL);
10327956Sxiuyan.wang@Sun.COM if ((ret != DDI_SUCCESS) || (actual == 0)) {
10337956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "ddi_intr_alloc() failure: %d\n", ret);
10347956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
10357956Sxiuyan.wang@Sun.COM }
10367956Sxiuyan.wang@Sun.COM
10377956Sxiuyan.wang@Sun.COM ret = ddi_intr_get_pri(adapter->intr_handle, &adapter->intr_pri);
10387956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
10397956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "ddi_intr_get_pri() failure: %d\n", ret);
10407956Sxiuyan.wang@Sun.COM }
10417956Sxiuyan.wang@Sun.COM
10427956Sxiuyan.wang@Sun.COM /* Call ddi_intr_add_handler() */
10437956Sxiuyan.wang@Sun.COM ret = ddi_intr_add_handler(adapter->intr_handle, unm_intr,
10447956Sxiuyan.wang@Sun.COM (caddr_t)adapter, NULL);
10457956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
10467956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: ddi_intr_add_handler() failure\n",
10477956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
10487956Sxiuyan.wang@Sun.COM (void) ddi_intr_free(adapter->intr_handle);
10497956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
10507956Sxiuyan.wang@Sun.COM }
10517956Sxiuyan.wang@Sun.COM
10527956Sxiuyan.wang@Sun.COM /* Add softintr if required */
10537956Sxiuyan.wang@Sun.COM
10547956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
10557956Sxiuyan.wang@Sun.COM
10567956Sxiuyan.wang@Sun.COM }
10577956Sxiuyan.wang@Sun.COM
10587956Sxiuyan.wang@Sun.COM void
unm_destroy_intr(unm_adapter * adapter)10597956Sxiuyan.wang@Sun.COM unm_destroy_intr(unm_adapter *adapter)
10607956Sxiuyan.wang@Sun.COM {
10617956Sxiuyan.wang@Sun.COM /* disable interrupt */
10627956Sxiuyan.wang@Sun.COM if (adapter->intr_type == DDI_INTR_TYPE_MSI)
10637956Sxiuyan.wang@Sun.COM (void) ddi_intr_block_disable(&adapter->intr_handle, 1);
10647956Sxiuyan.wang@Sun.COM else
10657956Sxiuyan.wang@Sun.COM (void) ddi_intr_disable(adapter->intr_handle);
10667956Sxiuyan.wang@Sun.COM
10677956Sxiuyan.wang@Sun.COM (void) ddi_intr_remove_handler(adapter->intr_handle);
10687956Sxiuyan.wang@Sun.COM (void) ddi_intr_free(adapter->intr_handle);
10697956Sxiuyan.wang@Sun.COM
10707956Sxiuyan.wang@Sun.COM /* Remove the software intr handler */
10717956Sxiuyan.wang@Sun.COM }
10727956Sxiuyan.wang@Sun.COM
10737956Sxiuyan.wang@Sun.COM static void
netxen_set_port_mode(unm_adapter * adapter)10747956Sxiuyan.wang@Sun.COM netxen_set_port_mode(unm_adapter *adapter)
10757956Sxiuyan.wang@Sun.COM {
10767956Sxiuyan.wang@Sun.COM static int wol_port_mode = UNM_PORT_MODE_AUTO_NEG_1G;
10777956Sxiuyan.wang@Sun.COM static int port_mode = UNM_PORT_MODE_AUTO_NEG;
10787956Sxiuyan.wang@Sun.COM int btype = adapter->ahw.boardcfg.board_type, data = 0;
10797956Sxiuyan.wang@Sun.COM
10807956Sxiuyan.wang@Sun.COM if (btype == UNM_BRDTYPE_P3_HMEZ || btype == UNM_BRDTYPE_P3_XG_LOM) {
10817956Sxiuyan.wang@Sun.COM data = port_mode; /* set to port_mode normally */
10827956Sxiuyan.wang@Sun.COM if ((port_mode != UNM_PORT_MODE_802_3_AP) &&
10837956Sxiuyan.wang@Sun.COM (port_mode != UNM_PORT_MODE_XG) &&
10847956Sxiuyan.wang@Sun.COM (port_mode != UNM_PORT_MODE_AUTO_NEG_1G) &&
10857956Sxiuyan.wang@Sun.COM (port_mode != UNM_PORT_MODE_AUTO_NEG_XG))
10867956Sxiuyan.wang@Sun.COM data = UNM_PORT_MODE_AUTO_NEG;
10877956Sxiuyan.wang@Sun.COM
10887956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_write_wx(adapter, UNM_PORT_MODE_ADDR,
10897956Sxiuyan.wang@Sun.COM &data, 4);
10907956Sxiuyan.wang@Sun.COM
10917956Sxiuyan.wang@Sun.COM if ((wol_port_mode != UNM_PORT_MODE_802_3_AP) &&
10927956Sxiuyan.wang@Sun.COM (wol_port_mode != UNM_PORT_MODE_XG) &&
10937956Sxiuyan.wang@Sun.COM (wol_port_mode != UNM_PORT_MODE_AUTO_NEG_1G) &&
10947956Sxiuyan.wang@Sun.COM (wol_port_mode != UNM_PORT_MODE_AUTO_NEG_XG))
10957956Sxiuyan.wang@Sun.COM wol_port_mode = UNM_PORT_MODE_AUTO_NEG;
10967956Sxiuyan.wang@Sun.COM
10977956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_write_wx(adapter, UNM_WOL_PORT_MODE,
10987956Sxiuyan.wang@Sun.COM &wol_port_mode, 4);
10997956Sxiuyan.wang@Sun.COM }
11007956Sxiuyan.wang@Sun.COM }
11017956Sxiuyan.wang@Sun.COM
11027956Sxiuyan.wang@Sun.COM static void
netxen_pcie_strap_init(unm_adapter * adapter)11037956Sxiuyan.wang@Sun.COM netxen_pcie_strap_init(unm_adapter *adapter)
11047956Sxiuyan.wang@Sun.COM {
11057956Sxiuyan.wang@Sun.COM ddi_acc_handle_t pcihdl = adapter->pci_cfg_handle;
11067956Sxiuyan.wang@Sun.COM u32 chicken, control, c8c9value = 0xF1000;
11077956Sxiuyan.wang@Sun.COM
11087956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_read_wx(adapter, UNM_PCIE_REG(PCIE_CHICKEN3),
11097956Sxiuyan.wang@Sun.COM &chicken, 4);
11107956Sxiuyan.wang@Sun.COM
11117956Sxiuyan.wang@Sun.COM chicken &= 0xFCFFFFFF; /* clear chicken3 25:24 */
11127956Sxiuyan.wang@Sun.COM control = pci_config_get32(pcihdl, 0xD0);
11137956Sxiuyan.wang@Sun.COM if ((control & 0x000F0000) != 0x00020000) /* is it gen1? */
11147956Sxiuyan.wang@Sun.COM chicken |= 0x01000000;
11157956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_write_wx(adapter, UNM_PCIE_REG(PCIE_CHICKEN3),
11167956Sxiuyan.wang@Sun.COM &chicken, 4);
11177956Sxiuyan.wang@Sun.COM control = pci_config_get32(pcihdl, 0xC8);
11187956Sxiuyan.wang@Sun.COM control = pci_config_get32(pcihdl, 0xC8);
11197956Sxiuyan.wang@Sun.COM pci_config_put32(pcihdl, 0xC8, c8c9value);
11207956Sxiuyan.wang@Sun.COM }
11217956Sxiuyan.wang@Sun.COM
11227956Sxiuyan.wang@Sun.COM static int
netxen_read_mac_addr(unm_adapter * adapter)11237956Sxiuyan.wang@Sun.COM netxen_read_mac_addr(unm_adapter *adapter)
11247956Sxiuyan.wang@Sun.COM {
1125*9436SJing.Xiong@Sun.COM u64 mac_addr[8 + 1];
11267956Sxiuyan.wang@Sun.COM unsigned char *p;
11277956Sxiuyan.wang@Sun.COM int i;
11287956Sxiuyan.wang@Sun.COM
11297956Sxiuyan.wang@Sun.COM if (get_flash_mac_addr(adapter, mac_addr) != 0)
11307956Sxiuyan.wang@Sun.COM return (-1);
11317956Sxiuyan.wang@Sun.COM
11327956Sxiuyan.wang@Sun.COM if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
11337956Sxiuyan.wang@Sun.COM p = (unsigned char *)&mac_addr[adapter->ahw.pci_func];
11347956Sxiuyan.wang@Sun.COM else
11357956Sxiuyan.wang@Sun.COM p = (unsigned char *)&mac_addr[adapter->portnum];
11367956Sxiuyan.wang@Sun.COM
11377956Sxiuyan.wang@Sun.COM for (i = 0; i < 6; i++)
11387956Sxiuyan.wang@Sun.COM adapter->mac_addr[i] = p[5 - i];
11397956Sxiuyan.wang@Sun.COM
11407956Sxiuyan.wang@Sun.COM if (unm_nic_macaddr_set(adapter, adapter->mac_addr) != 0)
11417956Sxiuyan.wang@Sun.COM return (-1);
11427956Sxiuyan.wang@Sun.COM
11437956Sxiuyan.wang@Sun.COM return (0);
11447956Sxiuyan.wang@Sun.COM }
11457956Sxiuyan.wang@Sun.COM
11467956Sxiuyan.wang@Sun.COM static int
unmattach(dev_info_t * dip,ddi_attach_cmd_t cmd)11477956Sxiuyan.wang@Sun.COM unmattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
11487956Sxiuyan.wang@Sun.COM {
11497956Sxiuyan.wang@Sun.COM unm_adapter *adapter;
11507956Sxiuyan.wang@Sun.COM int i, first_driver = 0;
1151*9436SJing.Xiong@Sun.COM int ret, temp;
11527956Sxiuyan.wang@Sun.COM
11537956Sxiuyan.wang@Sun.COM switch (cmd) {
11547956Sxiuyan.wang@Sun.COM case DDI_ATTACH:
11557956Sxiuyan.wang@Sun.COM break;
11567956Sxiuyan.wang@Sun.COM case DDI_RESUME:
11577956Sxiuyan.wang@Sun.COM case DDI_PM_RESUME:
11587956Sxiuyan.wang@Sun.COM default:
11597956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
11607956Sxiuyan.wang@Sun.COM }
11617956Sxiuyan.wang@Sun.COM
11627956Sxiuyan.wang@Sun.COM adapter = kmem_zalloc(sizeof (unm_adapter), KM_SLEEP);
11637956Sxiuyan.wang@Sun.COM adapter->dip = dip;
11647956Sxiuyan.wang@Sun.COM ddi_set_driver_private(dip, adapter);
11657956Sxiuyan.wang@Sun.COM adapter->instance = ddi_get_instance(dip);
11667956Sxiuyan.wang@Sun.COM
11677956Sxiuyan.wang@Sun.COM adapter->name = ddi_driver_name(dip);
11687956Sxiuyan.wang@Sun.COM
11697956Sxiuyan.wang@Sun.COM ret = pci_config_setup(dip, &adapter->pci_cfg_handle);
11707956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
11717956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: pci_config_setup failed\n",
11727956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
11737956Sxiuyan.wang@Sun.COM goto attach_setup_err;
11747956Sxiuyan.wang@Sun.COM }
11757956Sxiuyan.wang@Sun.COM
11767956Sxiuyan.wang@Sun.COM ret = unm_pci_cfg_init(adapter);
11777956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS)
11787956Sxiuyan.wang@Sun.COM goto attach_err;
11797956Sxiuyan.wang@Sun.COM
11807956Sxiuyan.wang@Sun.COM ret = unm_pci_map_setup(adapter);
11817956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS)
11827956Sxiuyan.wang@Sun.COM goto attach_err;
11837956Sxiuyan.wang@Sun.COM
11847956Sxiuyan.wang@Sun.COM if (unm_initialize_intr(adapter) != DDI_SUCCESS)
11857956Sxiuyan.wang@Sun.COM goto attach_unmap_regs;
11867956Sxiuyan.wang@Sun.COM
11877956Sxiuyan.wang@Sun.COM rw_init(&adapter->adapter_lock, NULL,
11887956Sxiuyan.wang@Sun.COM RW_DRIVER, DDI_INTR_PRI(adapter->intr_pri));
11897956Sxiuyan.wang@Sun.COM mutex_init(&adapter->tx_lock, NULL,
11907956Sxiuyan.wang@Sun.COM MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
11917956Sxiuyan.wang@Sun.COM mutex_init(&adapter->lock, NULL,
11927956Sxiuyan.wang@Sun.COM MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
11937956Sxiuyan.wang@Sun.COM
11947956Sxiuyan.wang@Sun.COM adapter->portnum = (int8_t)adapter->ahw.pci_func;
11957956Sxiuyan.wang@Sun.COM
11967956Sxiuyan.wang@Sun.COM /*
11977956Sxiuyan.wang@Sun.COM * Set the CRB window to invalid. If any register in window 0 is
11987956Sxiuyan.wang@Sun.COM * accessed it should set window to 0 and then reset it to 1.
11997956Sxiuyan.wang@Sun.COM */
12007956Sxiuyan.wang@Sun.COM adapter->curr_window = 255;
12017956Sxiuyan.wang@Sun.COM
12027956Sxiuyan.wang@Sun.COM adapter->fw_major = adapter->unm_nic_pci_read_normalize(adapter,
12037956Sxiuyan.wang@Sun.COM UNM_FW_VERSION_MAJOR);
12047956Sxiuyan.wang@Sun.COM
12057956Sxiuyan.wang@Sun.COM if (adapter->fw_major < 4)
12067956Sxiuyan.wang@Sun.COM adapter->max_rds_rings = 3;
12077956Sxiuyan.wang@Sun.COM else
12087956Sxiuyan.wang@Sun.COM adapter->max_rds_rings = 2;
12097956Sxiuyan.wang@Sun.COM
12107956Sxiuyan.wang@Sun.COM STRUCT_COPY(adapter->gc_dma_attr_desc, unm_dma_attr_desc);
12117956Sxiuyan.wang@Sun.COM STRUCT_COPY(adapter->gc_attr_desc, unm_buf_attr);
12127956Sxiuyan.wang@Sun.COM
12137956Sxiuyan.wang@Sun.COM ret = unm_nic_get_board_info(adapter);
12147956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
12157956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: error reading board config\n",
12167956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
12177956Sxiuyan.wang@Sun.COM goto attach_destroy_intr;
12187956Sxiuyan.wang@Sun.COM }
12197956Sxiuyan.wang@Sun.COM
12207956Sxiuyan.wang@Sun.COM /* Mezz cards have PCI function 0, 2, 3 enabled */
12217956Sxiuyan.wang@Sun.COM switch (adapter->ahw.boardcfg.board_type) {
12227956Sxiuyan.wang@Sun.COM case UNM_BRDTYPE_P2_SB31_10G_IMEZ:
12237956Sxiuyan.wang@Sun.COM case UNM_BRDTYPE_P2_SB31_10G_HMEZ:
12247956Sxiuyan.wang@Sun.COM if (adapter->ahw.pci_func >= 2) {
12257956Sxiuyan.wang@Sun.COM adapter->portnum = adapter->ahw.pci_func - 2;
12267956Sxiuyan.wang@Sun.COM }
12277956Sxiuyan.wang@Sun.COM default:
12287956Sxiuyan.wang@Sun.COM break;
12297956Sxiuyan.wang@Sun.COM }
12307956Sxiuyan.wang@Sun.COM
12317956Sxiuyan.wang@Sun.COM if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
12327956Sxiuyan.wang@Sun.COM temp = UNM_CRB_READ_VAL_ADAPTER(UNM_MIU_MN_CONTROL, adapter);
12337956Sxiuyan.wang@Sun.COM adapter->ahw.cut_through = NX_IS_SYSTEM_CUT_THROUGH(temp);
12347956Sxiuyan.wang@Sun.COM if (adapter->ahw.pci_func == 0)
12357956Sxiuyan.wang@Sun.COM first_driver = 1;
12367956Sxiuyan.wang@Sun.COM } else {
12377956Sxiuyan.wang@Sun.COM if (adapter->portnum == 0)
12387956Sxiuyan.wang@Sun.COM first_driver = 1;
12397956Sxiuyan.wang@Sun.COM }
12407956Sxiuyan.wang@Sun.COM
12417956Sxiuyan.wang@Sun.COM unm_check_options(adapter);
12427956Sxiuyan.wang@Sun.COM
12437956Sxiuyan.wang@Sun.COM if (first_driver) {
12447956Sxiuyan.wang@Sun.COM int first_boot = adapter->unm_nic_pci_read_normalize(adapter,
12457956Sxiuyan.wang@Sun.COM UNM_CAM_RAM(0x1fc));
12467956Sxiuyan.wang@Sun.COM
12477956Sxiuyan.wang@Sun.COM if (check_hw_init(adapter) != 0) {
12487956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: Error in HW init sequence\n",
12497956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
12507956Sxiuyan.wang@Sun.COM goto attach_destroy_intr;
12517956Sxiuyan.wang@Sun.COM }
12527956Sxiuyan.wang@Sun.COM
12537956Sxiuyan.wang@Sun.COM if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
12547956Sxiuyan.wang@Sun.COM netxen_set_port_mode(adapter);
12557956Sxiuyan.wang@Sun.COM
12567956Sxiuyan.wang@Sun.COM if (first_boot != 0x55555555) {
12577956Sxiuyan.wang@Sun.COM temp = 0;
12587956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_write_wx(adapter, CRB_CMDPEG_STATE,
12597956Sxiuyan.wang@Sun.COM &temp, 4);
12607956Sxiuyan.wang@Sun.COM if (pinit_from_rom(adapter, 0) != 0)
12617956Sxiuyan.wang@Sun.COM goto attach_destroy_intr;
12627956Sxiuyan.wang@Sun.COM
12637956Sxiuyan.wang@Sun.COM drv_usecwait(500);
12647956Sxiuyan.wang@Sun.COM
12657956Sxiuyan.wang@Sun.COM ret = load_from_flash(adapter);
12667956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS)
12677956Sxiuyan.wang@Sun.COM goto attach_destroy_intr;
12687956Sxiuyan.wang@Sun.COM }
12697956Sxiuyan.wang@Sun.COM
12707956Sxiuyan.wang@Sun.COM if (ret = unm_initialize_dummy_dma(adapter))
12717956Sxiuyan.wang@Sun.COM goto attach_destroy_intr;
12727956Sxiuyan.wang@Sun.COM
12737956Sxiuyan.wang@Sun.COM /*
12747956Sxiuyan.wang@Sun.COM * Tell the hardware our version number.
12757956Sxiuyan.wang@Sun.COM */
12767956Sxiuyan.wang@Sun.COM i = (_UNM_NIC_MAJOR << 16) |
12777956Sxiuyan.wang@Sun.COM ((_UNM_NIC_MINOR << 8)) | (_UNM_NIC_SUBVERSION);
12787956Sxiuyan.wang@Sun.COM adapter->unm_nic_hw_write_wx(adapter, CRB_DRIVER_VERSION,
12797956Sxiuyan.wang@Sun.COM &i, 4);
12807956Sxiuyan.wang@Sun.COM
12817956Sxiuyan.wang@Sun.COM /* Unlock the HW, prompting the boot sequence */
12827956Sxiuyan.wang@Sun.COM if ((first_boot == 0x55555555) &&
12837956Sxiuyan.wang@Sun.COM (NX_IS_REVISION_P2(adapter->ahw.revision_id)))
12847956Sxiuyan.wang@Sun.COM adapter->unm_nic_pci_write_normalize(adapter,
12857956Sxiuyan.wang@Sun.COM UNM_ROMUSB_GLB_PEGTUNE_DONE, 1);
12867956Sxiuyan.wang@Sun.COM
12877956Sxiuyan.wang@Sun.COM /* Handshake with the card before we register the devices. */
12887956Sxiuyan.wang@Sun.COM if (phantom_init(adapter, 0) != DDI_SUCCESS)
12897956Sxiuyan.wang@Sun.COM goto attach_destroy_intr;
12907956Sxiuyan.wang@Sun.COM }
12917956Sxiuyan.wang@Sun.COM
12927956Sxiuyan.wang@Sun.COM if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
12937956Sxiuyan.wang@Sun.COM netxen_pcie_strap_init(adapter);
12947956Sxiuyan.wang@Sun.COM
12957956Sxiuyan.wang@Sun.COM /*
12967956Sxiuyan.wang@Sun.COM * See if the firmware gave us a virtual-physical port mapping.
12977956Sxiuyan.wang@Sun.COM */
12987956Sxiuyan.wang@Sun.COM adapter->physical_port = adapter->portnum;
12997956Sxiuyan.wang@Sun.COM i = adapter->unm_nic_pci_read_normalize(adapter,
13007956Sxiuyan.wang@Sun.COM CRB_V2P(adapter->portnum));
13017956Sxiuyan.wang@Sun.COM if (i != 0x55555555)
13027956Sxiuyan.wang@Sun.COM adapter->physical_port = (uint16_t)i;
13037956Sxiuyan.wang@Sun.COM
13047956Sxiuyan.wang@Sun.COM adapter->ahw.linkup = 0;
13057956Sxiuyan.wang@Sun.COM
13067956Sxiuyan.wang@Sun.COM if (receive_peg_ready(adapter)) {
13077956Sxiuyan.wang@Sun.COM ret = -EIO;
1308*9436SJing.Xiong@Sun.COM goto free_dummy_dma;
13097956Sxiuyan.wang@Sun.COM }
13107956Sxiuyan.wang@Sun.COM
13117956Sxiuyan.wang@Sun.COM if (netxen_read_mac_addr(adapter))
13127956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "%s%d: Failed to read MAC addr\n",
13137956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
13147956Sxiuyan.wang@Sun.COM
13157956Sxiuyan.wang@Sun.COM unm_nic_flash_print(adapter);
13167956Sxiuyan.wang@Sun.COM
13177956Sxiuyan.wang@Sun.COM if (verbmsg != 0) {
13187956Sxiuyan.wang@Sun.COM switch (adapter->ahw.board_type) {
13197956Sxiuyan.wang@Sun.COM case UNM_NIC_GBE:
13207956Sxiuyan.wang@Sun.COM cmn_err(CE_NOTE, "%s: QUAD GbE port %d initialized\n",
13217956Sxiuyan.wang@Sun.COM unm_nic_driver_name, adapter->portnum);
13227956Sxiuyan.wang@Sun.COM break;
13237956Sxiuyan.wang@Sun.COM
13247956Sxiuyan.wang@Sun.COM case UNM_NIC_XGBE:
13257956Sxiuyan.wang@Sun.COM cmn_err(CE_NOTE, "%s: XGbE port %d initialized\n",
13267956Sxiuyan.wang@Sun.COM unm_nic_driver_name, adapter->portnum);
13277956Sxiuyan.wang@Sun.COM break;
13287956Sxiuyan.wang@Sun.COM }
13297956Sxiuyan.wang@Sun.COM }
13307956Sxiuyan.wang@Sun.COM
13317956Sxiuyan.wang@Sun.COM ret = unm_register_mac(adapter);
13327956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
13337956Sxiuyan.wang@Sun.COM cmn_err(CE_NOTE, "%s%d: Mac registration error\n",
13347956Sxiuyan.wang@Sun.COM adapter->name, adapter->instance);
1335*9436SJing.Xiong@Sun.COM goto free_dummy_dma;
13367956Sxiuyan.wang@Sun.COM }
13377956Sxiuyan.wang@Sun.COM
13387956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
13397956Sxiuyan.wang@Sun.COM
1340*9436SJing.Xiong@Sun.COM free_dummy_dma:
1341*9436SJing.Xiong@Sun.COM if (first_driver)
13427956Sxiuyan.wang@Sun.COM unm_free_dummy_dma(adapter);
13437956Sxiuyan.wang@Sun.COM attach_destroy_intr:
13447956Sxiuyan.wang@Sun.COM unm_destroy_intr(adapter);
13457956Sxiuyan.wang@Sun.COM attach_unmap_regs:
13467956Sxiuyan.wang@Sun.COM ddi_regs_map_free(&(adapter->regs_handle));
13477956Sxiuyan.wang@Sun.COM ddi_regs_map_free(&(adapter->db_handle));
13487956Sxiuyan.wang@Sun.COM attach_err:
13497956Sxiuyan.wang@Sun.COM pci_config_teardown(&adapter->pci_cfg_handle);
13507956Sxiuyan.wang@Sun.COM attach_setup_err:
13517956Sxiuyan.wang@Sun.COM kmem_free(adapter, sizeof (unm_adapter));
13527956Sxiuyan.wang@Sun.COM return (ret);
13537956Sxiuyan.wang@Sun.COM }
13547956Sxiuyan.wang@Sun.COM
13557956Sxiuyan.wang@Sun.COM static int
unmdetach(dev_info_t * dip,ddi_detach_cmd_t cmd)13567956Sxiuyan.wang@Sun.COM unmdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
13577956Sxiuyan.wang@Sun.COM {
13587956Sxiuyan.wang@Sun.COM unm_adapter *adapter = (unm_adapter *)ddi_get_driver_private(dip);
13597956Sxiuyan.wang@Sun.COM
13607956Sxiuyan.wang@Sun.COM if (adapter == NULL)
13617956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
13627956Sxiuyan.wang@Sun.COM
13637956Sxiuyan.wang@Sun.COM switch (cmd) {
13647956Sxiuyan.wang@Sun.COM case DDI_DETACH:
13657956Sxiuyan.wang@Sun.COM unm_fini_kstats(adapter);
13667956Sxiuyan.wang@Sun.COM adapter->kstats[0] = NULL;
13677956Sxiuyan.wang@Sun.COM
13687956Sxiuyan.wang@Sun.COM if (adapter->pci_cfg_handle != NULL)
1369*9436SJing.Xiong@Sun.COM pci_config_teardown(&adapter->pci_cfg_handle);
13707956Sxiuyan.wang@Sun.COM
13717956Sxiuyan.wang@Sun.COM unm_nd_cleanup(adapter);
13727956Sxiuyan.wang@Sun.COM unm_nic_remove(adapter);
13737956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
13747956Sxiuyan.wang@Sun.COM
13757956Sxiuyan.wang@Sun.COM case DDI_SUSPEND:
13767956Sxiuyan.wang@Sun.COM return (unm_nic_suspend(adapter));
13777956Sxiuyan.wang@Sun.COM
13787956Sxiuyan.wang@Sun.COM default:
13797956Sxiuyan.wang@Sun.COM break;
13807956Sxiuyan.wang@Sun.COM }
13817956Sxiuyan.wang@Sun.COM
13827956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
13837956Sxiuyan.wang@Sun.COM }
13847956Sxiuyan.wang@Sun.COM
1385*9436SJing.Xiong@Sun.COM int
create_rxtx_rings(unm_adapter * adapter)1386*9436SJing.Xiong@Sun.COM create_rxtx_rings(unm_adapter *adapter)
1387*9436SJing.Xiong@Sun.COM {
1388*9436SJing.Xiong@Sun.COM unm_recv_context_t *recv_ctx;
1389*9436SJing.Xiong@Sun.COM unm_rcv_desc_ctx_t *rcv_desc;
1390*9436SJing.Xiong@Sun.COM int i, ring;
1391*9436SJing.Xiong@Sun.COM
1392*9436SJing.Xiong@Sun.COM adapter->cmd_buf_arr = (struct unm_cmd_buffer *)kmem_zalloc(
1393*9436SJing.Xiong@Sun.COM sizeof (struct unm_cmd_buffer) * adapter->MaxTxDescCount,
1394*9436SJing.Xiong@Sun.COM KM_SLEEP);
1395*9436SJing.Xiong@Sun.COM
1396*9436SJing.Xiong@Sun.COM for (i = 0; i < MAX_RCV_CTX; ++i) {
1397*9436SJing.Xiong@Sun.COM recv_ctx = &adapter->recv_ctx[i];
1398*9436SJing.Xiong@Sun.COM
1399*9436SJing.Xiong@Sun.COM for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1400*9436SJing.Xiong@Sun.COM rcv_desc = &recv_ctx->rcv_desc[ring];
1401*9436SJing.Xiong@Sun.COM if (unm_create_rx_ring(adapter, rcv_desc) !=
1402*9436SJing.Xiong@Sun.COM DDI_SUCCESS)
1403*9436SJing.Xiong@Sun.COM goto attach_free_cmdbufs;
1404*9436SJing.Xiong@Sun.COM }
1405*9436SJing.Xiong@Sun.COM }
1406*9436SJing.Xiong@Sun.COM
1407*9436SJing.Xiong@Sun.COM if (unm_alloc_tx_dmahdl(adapter) != DDI_SUCCESS)
1408*9436SJing.Xiong@Sun.COM goto attach_free_cmdbufs;
1409*9436SJing.Xiong@Sun.COM
1410*9436SJing.Xiong@Sun.COM if (unm_alloc_tx_buffers(adapter) != DDI_SUCCESS)
1411*9436SJing.Xiong@Sun.COM goto attach_free_tx_dmahdl;
1412*9436SJing.Xiong@Sun.COM
1413*9436SJing.Xiong@Sun.COM return (DDI_SUCCESS);
1414*9436SJing.Xiong@Sun.COM
1415*9436SJing.Xiong@Sun.COM attach_free_tx_buffers:
1416*9436SJing.Xiong@Sun.COM unm_free_tx_buffers(adapter);
1417*9436SJing.Xiong@Sun.COM attach_free_tx_dmahdl:
1418*9436SJing.Xiong@Sun.COM unm_free_tx_dmahdl(adapter);
1419*9436SJing.Xiong@Sun.COM attach_free_cmdbufs:
1420*9436SJing.Xiong@Sun.COM kmem_free(adapter->cmd_buf_arr, sizeof (struct unm_cmd_buffer) *
1421*9436SJing.Xiong@Sun.COM adapter->MaxTxDescCount);
1422*9436SJing.Xiong@Sun.COM for (i = 0; i < MAX_RCV_CTX; ++i) {
1423*9436SJing.Xiong@Sun.COM recv_ctx = &adapter->recv_ctx[i];
1424*9436SJing.Xiong@Sun.COM
1425*9436SJing.Xiong@Sun.COM for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1426*9436SJing.Xiong@Sun.COM rcv_desc = &recv_ctx->rcv_desc[ring];
1427*9436SJing.Xiong@Sun.COM if (rcv_desc->rx_buf_pool != NULL)
1428*9436SJing.Xiong@Sun.COM unm_destroy_rx_ring(rcv_desc);
1429*9436SJing.Xiong@Sun.COM }
1430*9436SJing.Xiong@Sun.COM }
1431*9436SJing.Xiong@Sun.COM return (DDI_FAILURE);
1432*9436SJing.Xiong@Sun.COM }
1433*9436SJing.Xiong@Sun.COM
1434*9436SJing.Xiong@Sun.COM void
destroy_rxtx_rings(unm_adapter * adapter)1435*9436SJing.Xiong@Sun.COM destroy_rxtx_rings(unm_adapter *adapter)
1436*9436SJing.Xiong@Sun.COM {
1437*9436SJing.Xiong@Sun.COM unm_recv_context_t *recv_ctx;
1438*9436SJing.Xiong@Sun.COM unm_rcv_desc_ctx_t *rcv_desc;
1439*9436SJing.Xiong@Sun.COM int ctx, ring;
1440*9436SJing.Xiong@Sun.COM
1441*9436SJing.Xiong@Sun.COM unm_free_tx_buffers(adapter);
1442*9436SJing.Xiong@Sun.COM unm_free_tx_dmahdl(adapter);
1443*9436SJing.Xiong@Sun.COM
1444*9436SJing.Xiong@Sun.COM for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
1445*9436SJing.Xiong@Sun.COM recv_ctx = &adapter->recv_ctx[ctx];
1446*9436SJing.Xiong@Sun.COM for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1447*9436SJing.Xiong@Sun.COM rcv_desc = &recv_ctx->rcv_desc[ring];
1448*9436SJing.Xiong@Sun.COM if (rcv_desc->rx_buf_pool != NULL)
1449*9436SJing.Xiong@Sun.COM unm_destroy_rx_ring(rcv_desc);
1450*9436SJing.Xiong@Sun.COM }
1451*9436SJing.Xiong@Sun.COM }
1452*9436SJing.Xiong@Sun.COM
1453*9436SJing.Xiong@Sun.COM if (adapter->cmd_buf_arr != NULL)
1454*9436SJing.Xiong@Sun.COM kmem_free(adapter->cmd_buf_arr,
1455*9436SJing.Xiong@Sun.COM sizeof (struct unm_cmd_buffer) * adapter->MaxTxDescCount);
1456*9436SJing.Xiong@Sun.COM }
1457*9436SJing.Xiong@Sun.COM
14587956Sxiuyan.wang@Sun.COM #ifdef SOLARIS11
14597956Sxiuyan.wang@Sun.COM DDI_DEFINE_STREAM_OPS(unm_ops, nulldev, nulldev, unmattach, unmdetach,
14607956Sxiuyan.wang@Sun.COM nodev, NULL, D_MP, NULL, NULL);
14617956Sxiuyan.wang@Sun.COM #else
14627956Sxiuyan.wang@Sun.COM DDI_DEFINE_STREAM_OPS(unm_ops, nulldev, nulldev, unmattach, unmdetach,
14637956Sxiuyan.wang@Sun.COM nodev, NULL, D_MP, NULL);
14647956Sxiuyan.wang@Sun.COM #endif
14657956Sxiuyan.wang@Sun.COM
14667956Sxiuyan.wang@Sun.COM static struct modldrv modldrv = {
14677956Sxiuyan.wang@Sun.COM &mod_driverops, /* Type of module. This one is a driver */
14687956Sxiuyan.wang@Sun.COM ident,
14697956Sxiuyan.wang@Sun.COM &unm_ops, /* driver ops */
14707956Sxiuyan.wang@Sun.COM };
14717956Sxiuyan.wang@Sun.COM
14727956Sxiuyan.wang@Sun.COM static struct modlinkage modlinkage = {
14737956Sxiuyan.wang@Sun.COM MODREV_1,
14747956Sxiuyan.wang@Sun.COM (&modldrv),
14757956Sxiuyan.wang@Sun.COM NULL
14767956Sxiuyan.wang@Sun.COM };
14777956Sxiuyan.wang@Sun.COM
14787956Sxiuyan.wang@Sun.COM
14797956Sxiuyan.wang@Sun.COM int
_init(void)14807956Sxiuyan.wang@Sun.COM _init(void)
14817956Sxiuyan.wang@Sun.COM {
14827956Sxiuyan.wang@Sun.COM int ret;
14837956Sxiuyan.wang@Sun.COM
14847956Sxiuyan.wang@Sun.COM unm_ops.devo_cb_ops->cb_str = NULL;
14857956Sxiuyan.wang@Sun.COM mac_init_ops(&unm_ops, "ntxn");
14867956Sxiuyan.wang@Sun.COM
14877956Sxiuyan.wang@Sun.COM ret = mod_install(&modlinkage);
14887956Sxiuyan.wang@Sun.COM if (ret != DDI_SUCCESS) {
14897956Sxiuyan.wang@Sun.COM mac_fini_ops(&unm_ops);
14907956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN, "ntxn: mod_install failed\n");
14917956Sxiuyan.wang@Sun.COM }
14927956Sxiuyan.wang@Sun.COM
14937956Sxiuyan.wang@Sun.COM return (ret);
14947956Sxiuyan.wang@Sun.COM }
14957956Sxiuyan.wang@Sun.COM
14967956Sxiuyan.wang@Sun.COM
14977956Sxiuyan.wang@Sun.COM int
_fini(void)14987956Sxiuyan.wang@Sun.COM _fini(void)
14997956Sxiuyan.wang@Sun.COM {
15007956Sxiuyan.wang@Sun.COM int ret;
15017956Sxiuyan.wang@Sun.COM
15027956Sxiuyan.wang@Sun.COM ret = mod_remove(&modlinkage);
15037956Sxiuyan.wang@Sun.COM if (ret == DDI_SUCCESS)
15047956Sxiuyan.wang@Sun.COM mac_fini_ops(&unm_ops);
15057956Sxiuyan.wang@Sun.COM return (ret);
15067956Sxiuyan.wang@Sun.COM }
15077956Sxiuyan.wang@Sun.COM
15087956Sxiuyan.wang@Sun.COM int
_info(struct modinfo * modinfop)15097956Sxiuyan.wang@Sun.COM _info(struct modinfo *modinfop)
15107956Sxiuyan.wang@Sun.COM {
15117956Sxiuyan.wang@Sun.COM return (mod_info(&modlinkage, modinfop));
15127956Sxiuyan.wang@Sun.COM }
1513