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