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