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 2010 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 
  50 #include <sys/gld.h>
  51 #include <netinet/in.h>
  52 #include <inet/ip.h>
  53 #include <inet/tcp.h>
  54 
  55 #include <sys/rwlock.h>
  56 #include <sys/mutex.h>
  57 #include <sys/pattr.h>
  58 #include <sys/strsubr.h>
  59 #include <sys/ddi_impldefs.h>
  60 #include<sys/task.h>
  61 
  62 #include "unm_nic_hw.h"
  63 #include "unm_nic.h"
  64 
  65 #include "nic_phan_reg.h"
  66 #include "unm_nic_ioctl.h"
  67 #include "nic_cmn.h"
  68 #include "unm_version.h"
  69 #include "unm_brdcfg.h"
  70 
  71 #if defined(lint)
  72 #undef MBLKL
  73 #define MBLKL(_mp_)     ((uintptr_t)(_mp_)->b_wptr - (uintptr_t)(_mp_)->b_rptr)
  74 #endif /* lint */
  75 
  76 #undef UNM_LOOPBACK
  77 #undef SINGLE_DMA_BUF
  78 
  79 #define UNM_ADAPTER_UP_MAGIC    777
  80 #define VLAN_TAGSZ              0x4
  81 
  82 #define index2rxbuf(_rdp_, _idx_)       ((_rdp_)->rx_buf_pool + (_idx_))
  83 #define rxbuf2index(_rdp_, _bufp_)      ((_bufp_) - (_rdp_)->rx_buf_pool)
  84 
  85 /*
  86  * Receive ISR processes NX_RX_MAXBUFS incoming packets at most, then posts
  87  * as many buffers as packets processed. This loop repeats as required to
  88  * process all incoming packets delivered in a single interrupt. Higher
  89  * value of NX_RX_MAXBUFS improves performance by posting rx buffers less
  90  * frequently, but at the cost of not posting quickly enough when card is
  91  * running out of rx buffers.
  92  */
  93 #define NX_RX_THRESHOLD         32
  94 #define NX_RX_MAXBUFS           128
  95 #define NX_MAX_TXCOMPS          256
  96 
  97 extern int create_rxtx_rings(unm_adapter *adapter);
  98 extern void destroy_rxtx_rings(unm_adapter *adapter);
  99 
 100 static void unm_post_rx_buffers_nodb(struct unm_adapter_s *adapter,
 101     uint32_t ringid);
 102 static mblk_t *unm_process_rcv(unm_adapter *adapter, statusDesc_t *desc);
 103 static int unm_process_rcv_ring(unm_adapter *, int);
 104 static int unm_process_cmd_ring(struct unm_adapter_s *adapter);
 105 
 106 static int unm_nic_do_ioctl(unm_adapter *adapter, queue_t *q, mblk_t *mp);
 107 static void unm_nic_ioctl(struct unm_adapter_s *adapter, int cmd, queue_t *q,
 108     mblk_t *mp);
 109 
 110 /* GLDv3 interface functions */
 111 static int ntxn_m_start(void *);
 112 static void ntxn_m_stop(void *);
 113 static int ntxn_m_multicst(void *, boolean_t, const uint8_t *);
 114 static int ntxn_m_promisc(void *, boolean_t);
 115 static int ntxn_m_stat(void *arg, uint_t stat, uint64_t *val);
 116 static mblk_t *ntxn_m_tx(void *, mblk_t *);
 117 static void ntxn_m_ioctl(void *arg, queue_t *wq, mblk_t *mp);
 118 static boolean_t ntxn_m_getcapab(void *arg, mac_capab_t cap, void *cap_data);
 119 
 120 /*
 121  * Allocates DMA handle, virtual memory and binds them
 122  * returns size of actual memory binded and the physical address.
 123  */
 124 int
 125 unm_pci_alloc_consistent(unm_adapter *adapter,
 126                 int size, caddr_t *address, ddi_dma_cookie_t *cookie,
 127                 ddi_dma_handle_t *dma_handle, ddi_acc_handle_t *handlep)
 128 {
 129         int                     err;
 130         uint32_t                ncookies;
 131         size_t                  ring_len;
 132         uint_t                  dma_flags = DDI_DMA_RDWR | DDI_DMA_CONSISTENT;
 133 
 134         *dma_handle = NULL;
 135 
 136         if (size <= 0)
 137                 return (DDI_ENOMEM);
 138 
 139         err = ddi_dma_alloc_handle(adapter->dip,
 140             &adapter->gc_dma_attr_desc,
 141             DDI_DMA_DONTWAIT, NULL, dma_handle);
 142         if (err != DDI_SUCCESS) {
 143                 cmn_err(CE_WARN, "!%s: %s: ddi_dma_alloc_handle FAILED:"
 144                     " %d", unm_nic_driver_name, __func__, err);
 145                 return (DDI_ENOMEM);
 146         }
 147 
 148         err = ddi_dma_mem_alloc(*dma_handle,
 149             size, &adapter->gc_attr_desc,
 150             dma_flags & (DDI_DMA_STREAMING | DDI_DMA_CONSISTENT),
 151             DDI_DMA_DONTWAIT, NULL, address, &ring_len,
 152             handlep);
 153         if (err != DDI_SUCCESS) {
 154                 cmn_err(CE_WARN, "!%s: %s: ddi_dma_mem_alloc failed:"
 155                     "ret %d, request size: %d",
 156                     unm_nic_driver_name, __func__, err, size);
 157                 ddi_dma_free_handle(dma_handle);
 158                 return (DDI_ENOMEM);
 159         }
 160 
 161         if (ring_len < size) {
 162                 cmn_err(CE_WARN, "%s: %s: could not allocate required "
 163                     "memory :%d\n", unm_nic_driver_name,
 164                     __func__, err);
 165                 ddi_dma_mem_free(handlep);
 166                 ddi_dma_free_handle(dma_handle);
 167                 return (DDI_FAILURE);
 168         }
 169 
 170         (void) memset(*address, 0, size);
 171 
 172         if (((err = ddi_dma_addr_bind_handle(*dma_handle,
 173             NULL, *address, ring_len,
 174             dma_flags,
 175             DDI_DMA_DONTWAIT, NULL,
 176             cookie, &ncookies)) != DDI_DMA_MAPPED) ||
 177             (ncookies != 1)) {
 178                 cmn_err(CE_WARN,
 179                     "!%s: %s: ddi_dma_addr_bind_handle FAILED: %d",
 180                     unm_nic_driver_name, __func__, err);
 181                 ddi_dma_mem_free(handlep);
 182                 ddi_dma_free_handle(dma_handle);
 183                 return (DDI_FAILURE);
 184         }
 185 
 186         return (DDI_SUCCESS);
 187 }
 188 
 189 /*
 190  * Unbinds the memory, frees the DMA handle and at the end, frees the memory
 191  */
 192 void
 193 unm_pci_free_consistent(ddi_dma_handle_t *dma_handle,
 194     ddi_acc_handle_t *acc_handle)
 195 {
 196         int err;
 197 
 198         err = ddi_dma_unbind_handle(*dma_handle);
 199         if (err != DDI_SUCCESS) {
 200                 cmn_err(CE_WARN, "%s: Error unbinding memory\n", __func__);
 201                 return;
 202         }
 203 
 204         ddi_dma_mem_free(acc_handle);
 205         ddi_dma_free_handle(dma_handle);
 206 }
 207 
 208 static uint32_t msi_tgt_status[] = {
 209     ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
 210     ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
 211     ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
 212     ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
 213 };
 214 
 215 static void
 216 unm_nic_disable_int(unm_adapter *adapter)
 217 {
 218         __uint32_t      temp = 0;
 219 
 220         adapter->unm_nic_hw_write_wx(adapter, adapter->interrupt_crb,
 221             &temp, 4);
 222 }
 223 
 224 static inline int
 225 unm_nic_clear_int(unm_adapter *adapter)
 226 {
 227         uint32_t        mask, temp, our_int, status;
 228 
 229         UNM_READ_LOCK(&adapter->adapter_lock);
 230 
 231         /* check whether it's our interrupt */
 232         if (!UNM_IS_MSI_FAMILY(adapter)) {
 233 
 234                 /* Legacy Interrupt case */
 235                 adapter->unm_nic_pci_read_immediate(adapter, ISR_INT_VECTOR,
 236                     &status);
 237 
 238                 if (!(status & adapter->legacy_intr.int_vec_bit)) {
 239                         UNM_READ_UNLOCK(&adapter->adapter_lock);
 240                         return (-1);
 241                 }
 242 
 243                 if (adapter->ahw.revision_id >= NX_P3_B1) {
 244                         adapter->unm_nic_pci_read_immediate(adapter,
 245                             ISR_INT_STATE_REG, &temp);
 246                         if (!ISR_IS_LEGACY_INTR_TRIGGERED(temp)) {
 247                                 UNM_READ_UNLOCK(&adapter->adapter_lock);
 248                                 return (-1);
 249                         }
 250                 } else if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
 251                         our_int = adapter->unm_nic_pci_read_normalize(adapter,
 252                             CRB_INT_VECTOR);
 253 
 254                         /* FIXME: Assumes pci_func is same as ctx */
 255                         if ((our_int & (0x80 << adapter->portnum)) == 0) {
 256                                 if (our_int != 0) {
 257                                         /* not our interrupt */
 258                                         UNM_READ_UNLOCK(&adapter->adapter_lock);
 259                                         return (-1);
 260                                 }
 261                         }
 262                         temp = our_int & ~((u32)(0x80 << adapter->portnum));
 263                         adapter->unm_nic_pci_write_normalize(adapter,
 264                             CRB_INT_VECTOR, temp);
 265                 }
 266 
 267                 if (adapter->fw_major < 4)
 268                         unm_nic_disable_int(adapter);
 269 
 270                 /* claim interrupt */
 271                 temp = 0xffffffff;
 272                 adapter->unm_nic_pci_write_immediate(adapter,
 273                     adapter->legacy_intr.tgt_status_reg, &temp);
 274 
 275                 adapter->unm_nic_pci_read_immediate(adapter, ISR_INT_VECTOR,
 276                     &mask);
 277 
 278                 /*
 279                  * Read again to make sure the legacy interrupt message got
 280                  * flushed out
 281                  */
 282                 adapter->unm_nic_pci_read_immediate(adapter, ISR_INT_VECTOR,
 283                     &mask);
 284         } else if (adapter->flags & UNM_NIC_MSI_ENABLED) {
 285                 /* clear interrupt */
 286                 temp = 0xffffffff;
 287                 adapter->unm_nic_pci_write_immediate(adapter,
 288                     msi_tgt_status[adapter->ahw.pci_func], &temp);
 289         }
 290 
 291         UNM_READ_UNLOCK(&adapter->adapter_lock);
 292 
 293         return (0);
 294 }
 295 
 296 static void
 297 unm_nic_enable_int(unm_adapter *adapter)
 298 {
 299         u32     temp = 1;
 300 
 301         adapter->unm_nic_hw_write_wx(adapter, adapter->interrupt_crb,
 302             &temp, 4);
 303 
 304         if (!UNM_IS_MSI_FAMILY(adapter)) {
 305                 u32     mask = 0xfbff;
 306 
 307                 adapter->unm_nic_pci_write_immediate(adapter,
 308                     adapter->legacy_intr.tgt_mask_reg, &mask);
 309         }
 310 }
 311 
 312 static void
 313 unm_free_hw_resources(unm_adapter *adapter)
 314 {
 315         unm_recv_context_t *recv_ctx;
 316         unm_rcv_desc_ctx_t *rcv_desc;
 317         int ctx, ring;
 318 
 319         if (adapter->context_alloced == 1) {
 320                 netxen_destroy_rxtx(adapter);
 321                 adapter->context_alloced = 0;
 322         }
 323 
 324         if (adapter->ctxDesc != NULL) {
 325                 unm_pci_free_consistent(&adapter->ctxDesc_dma_handle,
 326                     &adapter->ctxDesc_acc_handle);
 327                 adapter->ctxDesc = NULL;
 328         }
 329 
 330         if (adapter->ahw.cmdDescHead != NULL) {
 331                 unm_pci_free_consistent(&adapter->ahw.cmd_desc_dma_handle,
 332                     &adapter->ahw.cmd_desc_acc_handle);
 333                 adapter->ahw.cmdDesc_physAddr = NULL;
 334                 adapter->ahw.cmdDescHead = NULL;
 335         }
 336 
 337         for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
 338                 recv_ctx = &adapter->recv_ctx[ctx];
 339                 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 340                         rcv_desc = &recv_ctx->rcv_desc[ring];
 341 
 342                         if (rcv_desc->desc_head != NULL) {
 343                                 unm_pci_free_consistent(
 344                                     &rcv_desc->rx_desc_dma_handle,
 345                                     &rcv_desc->rx_desc_acc_handle);
 346                                 rcv_desc->desc_head = NULL;
 347                                 rcv_desc->phys_addr = NULL;
 348                         }
 349                 }
 350 
 351                 if (recv_ctx->rcvStatusDescHead != NULL) {
 352                         unm_pci_free_consistent(
 353                             &recv_ctx->status_desc_dma_handle,
 354                             &recv_ctx->status_desc_acc_handle);
 355                         recv_ctx->rcvStatusDesc_physAddr = NULL;
 356                         recv_ctx->rcvStatusDescHead = NULL;
 357                 }
 358         }
 359 }
 360 
 361 static void
 362 cleanup_adapter(struct unm_adapter_s *adapter)
 363 {
 364         ddi_regs_map_free(&(adapter->regs_handle));
 365         ddi_regs_map_free(&(adapter->db_handle));
 366         kmem_free(adapter, sizeof (unm_adapter));
 367 }
 368 
 369 void
 370 unm_nic_remove(unm_adapter *adapter)
 371 {
 372         mac_link_update(adapter->mach, LINK_STATE_DOWN);
 373         unm_nic_stop_port(adapter);
 374 
 375         if (adapter->interrupt_crb) {
 376                 UNM_READ_LOCK(&adapter->adapter_lock);
 377                 unm_nic_disable_int(adapter);
 378                 UNM_READ_UNLOCK(&adapter->adapter_lock);
 379         }
 380         (void) untimeout(adapter->watchdog_timer);
 381 
 382         unm_free_hw_resources(adapter);
 383 
 384         if (adapter->is_up == UNM_ADAPTER_UP_MAGIC)
 385                 destroy_rxtx_rings(adapter);
 386 
 387         if (adapter->portnum == 0)
 388                 unm_free_dummy_dma(adapter);
 389 
 390         unm_destroy_intr(adapter);
 391 
 392         ddi_set_driver_private(adapter->dip, NULL);
 393         cleanup_adapter(adapter);
 394 }
 395 
 396 static int
 397 init_firmware(unm_adapter *adapter)
 398 {
 399         uint32_t state = 0, loops = 0, tempout;
 400 
 401         /* Window 1 call */
 402         UNM_READ_LOCK(&adapter->adapter_lock);
 403         state = adapter->unm_nic_pci_read_normalize(adapter, CRB_CMDPEG_STATE);
 404         UNM_READ_UNLOCK(&adapter->adapter_lock);
 405 
 406         if (state == PHAN_INITIALIZE_ACK)
 407                 return (0);
 408 
 409         while (state != PHAN_INITIALIZE_COMPLETE && loops < 200000) {
 410                 drv_usecwait(100);
 411                 /* Window 1 call */
 412                 UNM_READ_LOCK(&adapter->adapter_lock);
 413                 state = adapter->unm_nic_pci_read_normalize(adapter,
 414                     CRB_CMDPEG_STATE);
 415                 UNM_READ_UNLOCK(&adapter->adapter_lock);
 416                 loops++;
 417         }
 418 
 419         if (loops >= 200000) {
 420                 cmn_err(CE_WARN, "%s%d: CmdPeg init incomplete:%x\n",
 421                     adapter->name, adapter->instance, state);
 422                 return (-EIO);
 423         }
 424 
 425         /* Window 1 call */
 426         UNM_READ_LOCK(&adapter->adapter_lock);
 427         tempout = INTR_SCHEME_PERPORT;
 428         adapter->unm_nic_hw_write_wx(adapter, CRB_NIC_CAPABILITIES_HOST,
 429             &tempout, 4);
 430         tempout = MSI_MODE_MULTIFUNC;
 431         adapter->unm_nic_hw_write_wx(adapter, CRB_NIC_MSI_MODE_HOST,
 432             &tempout, 4);
 433         tempout = MPORT_MULTI_FUNCTION_MODE;
 434         adapter->unm_nic_hw_write_wx(adapter, CRB_MPORT_MODE, &tempout, 4);
 435         tempout = PHAN_INITIALIZE_ACK;
 436         adapter->unm_nic_hw_write_wx(adapter, CRB_CMDPEG_STATE, &tempout, 4);
 437         UNM_READ_UNLOCK(&adapter->adapter_lock);
 438 
 439         return (0);
 440 }
 441 
 442 /*
 443  * Utility to synchronize with receive peg.
 444  *  Returns   0 on sucess
 445  *         -EIO on error
 446  */
 447 int
 448 receive_peg_ready(struct unm_adapter_s *adapter)
 449 {
 450         uint32_t state = 0;
 451         int loops = 0, err = 0;
 452 
 453         /* Window 1 call */
 454         UNM_READ_LOCK(&adapter->adapter_lock);
 455         state = adapter->unm_nic_pci_read_normalize(adapter, CRB_RCVPEG_STATE);
 456         UNM_READ_UNLOCK(&adapter->adapter_lock);
 457 
 458         while ((state != PHAN_PEG_RCV_INITIALIZED) && (loops < 20000)) {
 459                 drv_usecwait(100);
 460                 /* Window 1 call */
 461 
 462                 UNM_READ_LOCK(&adapter->adapter_lock);
 463                 state = adapter->unm_nic_pci_read_normalize(adapter,
 464                     CRB_RCVPEG_STATE);
 465                 UNM_READ_UNLOCK(&adapter->adapter_lock);
 466 
 467                 loops++;
 468         }
 469 
 470         if (loops >= 20000) {
 471                 cmn_err(CE_WARN, "Receive Peg initialization incomplete 0x%x\n",
 472                     state);
 473                 err = -EIO;
 474         }
 475 
 476         return (err);
 477 }
 478 
 479 /*
 480  * check if the firmware has been downloaded and ready to run  and
 481  * setup the address for the descriptors in the adapter
 482  */
 483 static int
 484 unm_nic_hw_resources(unm_adapter *adapter)
 485 {
 486         hardware_context        *hw = &adapter->ahw;
 487         void                    *addr;
 488         int                     err;
 489         int                     ctx, ring;
 490         unm_recv_context_t      *recv_ctx;
 491         unm_rcv_desc_ctx_t      *rcv_desc;
 492         ddi_dma_cookie_t        cookie;
 493         int                     size;
 494 
 495         if (err = receive_peg_ready(adapter))
 496                 return (err);
 497 
 498         size = (sizeof (RingContext) + sizeof (uint32_t));
 499 
 500         err = unm_pci_alloc_consistent(adapter,
 501             size, (caddr_t *)&addr, &cookie,
 502             &adapter->ctxDesc_dma_handle,
 503             &adapter->ctxDesc_acc_handle);
 504         if (err != DDI_SUCCESS) {
 505                 cmn_err(CE_WARN, "Failed to allocate HW context\n");
 506                 return (err);
 507         }
 508 
 509         adapter->ctxDesc_physAddr = cookie.dmac_laddress;
 510 
 511         (void) memset(addr, 0, sizeof (RingContext));
 512 
 513         adapter->ctxDesc = (RingContext *) addr;
 514         adapter->ctxDesc->CtxId = adapter->portnum;
 515         adapter->ctxDesc->CMD_CONSUMER_OFFSET =
 516             adapter->ctxDesc_physAddr + sizeof (RingContext);
 517         adapter->cmdConsumer =
 518             (uint32_t *)(uintptr_t)(((char *)addr) + sizeof (RingContext));
 519 
 520         ASSERT(!((unsigned long)adapter->ctxDesc_physAddr & 0x3f));
 521 
 522         /*
 523          * Allocate command descriptor ring.
 524          */
 525         size = (sizeof (cmdDescType0_t) * adapter->MaxTxDescCount);
 526         err = unm_pci_alloc_consistent(adapter,
 527             size, (caddr_t *)&addr, &cookie,
 528             &hw->cmd_desc_dma_handle,
 529             &hw->cmd_desc_acc_handle);
 530         if (err != DDI_SUCCESS) {
 531                 cmn_err(CE_WARN, "Failed to allocate cmd desc ring\n");
 532                 return (err);
 533         }
 534 
 535         hw->cmdDesc_physAddr = cookie.dmac_laddress;
 536         hw->cmdDescHead = (cmdDescType0_t *)addr;
 537 
 538         for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
 539                 recv_ctx = &adapter->recv_ctx[ctx];
 540 
 541                 size = (sizeof (statusDesc_t)* adapter->MaxRxDescCount);
 542                 err = unm_pci_alloc_consistent(adapter,
 543                     size, (caddr_t *)&addr,
 544                     &recv_ctx->status_desc_dma_cookie,
 545                     &recv_ctx->status_desc_dma_handle,
 546                     &recv_ctx->status_desc_acc_handle);
 547                 if (err != DDI_SUCCESS) {
 548                         cmn_err(CE_WARN, "Failed to allocate sts desc ring\n");
 549                         goto free_cmd_desc;
 550                 }
 551 
 552                 (void) memset(addr, 0, size);
 553                 recv_ctx->rcvStatusDesc_physAddr =
 554                     recv_ctx->status_desc_dma_cookie.dmac_laddress;
 555                 recv_ctx->rcvStatusDescHead = (statusDesc_t *)addr;
 556 
 557                 /* rds rings */
 558                 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 559                         rcv_desc = &recv_ctx->rcv_desc[ring];
 560 
 561                         size = (sizeof (rcvDesc_t) * adapter->MaxRxDescCount);
 562                         err = unm_pci_alloc_consistent(adapter,
 563                             size, (caddr_t *)&addr,
 564                             &rcv_desc->rx_desc_dma_cookie,
 565                             &rcv_desc->rx_desc_dma_handle,
 566                             &rcv_desc->rx_desc_acc_handle);
 567                         if (err != DDI_SUCCESS) {
 568                                 cmn_err(CE_WARN, "Failed to allocate "
 569                                     "rx desc ring %d\n", ring);
 570                                 goto free_status_desc;
 571                         }
 572 
 573                         rcv_desc->phys_addr =
 574                             rcv_desc->rx_desc_dma_cookie.dmac_laddress;
 575                         rcv_desc->desc_head = (rcvDesc_t *)addr;
 576                 }
 577         }
 578 
 579         if (err = netxen_create_rxtx(adapter))
 580                 goto free_statusrx_desc;
 581         adapter->context_alloced = 1;
 582 
 583         return (DDI_SUCCESS);
 584 
 585 free_statusrx_desc:
 586 free_status_desc:
 587 free_cmd_desc:
 588         unm_free_hw_resources(adapter);
 589 
 590         return (err);
 591 }
 592 
 593 void unm_desc_dma_sync(ddi_dma_handle_t handle, uint_t start, uint_t count,
 594     uint_t range, uint_t unit_size, uint_t direction)
 595 {
 596         if ((start + count) < range) {
 597                 (void) ddi_dma_sync(handle, start * unit_size,
 598                     count * unit_size, direction);
 599         } else {
 600                 (void) ddi_dma_sync(handle, start * unit_size, 0, direction);
 601                 (void) ddi_dma_sync(handle, 0,
 602                     (start + count - range) * unit_size, DDI_DMA_SYNC_FORCPU);
 603         }
 604 }
 605 
 606 static uint32_t crb_cmd_producer[4] = { CRB_CMD_PRODUCER_OFFSET,
 607     CRB_CMD_PRODUCER_OFFSET_1, CRB_CMD_PRODUCER_OFFSET_2,
 608     CRB_CMD_PRODUCER_OFFSET_3 };
 609 
 610 static uint32_t crb_cmd_consumer[4] = { CRB_CMD_CONSUMER_OFFSET,
 611     CRB_CMD_CONSUMER_OFFSET_1, CRB_CMD_CONSUMER_OFFSET_2,
 612     CRB_CMD_CONSUMER_OFFSET_3 };
 613 
 614 void
 615 unm_nic_update_cmd_producer(struct unm_adapter_s *adapter,
 616     uint32_t crb_producer)
 617 {
 618         int data = crb_producer;
 619 
 620         if (adapter->crb_addr_cmd_producer) {
 621                 UNM_READ_LOCK(&adapter->adapter_lock);
 622                 adapter->unm_nic_hw_write_wx(adapter,
 623                     adapter->crb_addr_cmd_producer, &data, 4);
 624                 UNM_READ_UNLOCK(&adapter->adapter_lock);
 625         }
 626 }
 627 
 628 static void
 629 unm_nic_update_cmd_consumer(struct unm_adapter_s *adapter,
 630     uint32_t crb_producer)
 631 {
 632         int data = crb_producer;
 633 
 634         if (adapter->crb_addr_cmd_consumer)
 635                 adapter->unm_nic_hw_write_wx(adapter,
 636                     adapter->crb_addr_cmd_consumer, &data, 4);
 637 }
 638 
 639 /*
 640  * Looks for type of packet and sets opcode accordingly
 641  * so that checksum offload can be used.
 642  */
 643 static void
 644 unm_tx_csum(cmdDescType0_t *desc, mblk_t *mp, pktinfo_t *pktinfo)
 645 {
 646         if (pktinfo->mac_hlen == sizeof (struct ether_vlan_header))
 647                 desc->u1.s1.flags = FLAGS_VLAN_TAGGED;
 648 
 649         if (pktinfo->etype == htons(ETHERTYPE_IP)) {
 650                 uint32_t        start, flags;
 651 
 652                 mac_hcksum_get(mp, &start, NULL, NULL, NULL, &flags);
 653                 if ((flags & (HCK_FULLCKSUM | HCK_IPV4_HDRCKSUM)) == 0)
 654                         return;
 655 
 656                 /*
 657                  * For TCP/UDP, ask hardware to do both IP header and
 658                  * full checksum, even if stack has already done one or
 659                  * the other. Hardware will always get it correct even
 660                  * if stack has already done it.
 661                  */
 662                 switch (pktinfo->l4_proto) {
 663                         case IPPROTO_TCP:
 664                                 desc->u1.s1.opcode = TX_TCP_PKT;
 665                                 break;
 666                         case IPPROTO_UDP:
 667                                 desc->u1.s1.opcode = TX_UDP_PKT;
 668                                 break;
 669                         default:
 670                                 /* Must be here with HCK_IPV4_HDRCKSUM */
 671                                 desc->u1.s1.opcode = TX_IP_PKT;
 672                                 return;
 673                 }
 674 
 675                 desc->u1.s1.ipHdrOffset = pktinfo->mac_hlen;
 676                 desc->u1.s1.tcpHdrOffset = pktinfo->mac_hlen + pktinfo->ip_hlen;
 677         }
 678 }
 679 
 680 /*
 681  * For IP/UDP/TCP checksum offload, this checks for MAC+IP header in one
 682  * contiguous block ending at 8 byte aligned address as required by hardware.
 683  * Caller assumes pktinfo->total_len will be updated by this function and
 684  * if pktinfo->etype is set to 0, it will need to linearize the mblk and
 685  * invoke unm_update_pkt_info() to determine ethertype, IP header len and
 686  * protocol.
 687  */
 688 static boolean_t
 689 unm_get_pkt_info(mblk_t *mp, pktinfo_t *pktinfo)
 690 {
 691         mblk_t          *bp;
 692         ushort_t        type;
 693 
 694         (void) memset(pktinfo, 0, sizeof (pktinfo_t));
 695 
 696         for (bp = mp; bp != NULL; bp = bp->b_cont) {
 697                 if (MBLKL(bp) == 0)
 698                         continue;
 699                 pktinfo->mblk_no++;
 700                 pktinfo->total_len += MBLKL(bp);
 701         }
 702 
 703         if (MBLKL(mp) < (sizeof (struct ether_header) + sizeof (ipha_t)))
 704                 return (B_FALSE);
 705 
 706         /*
 707          * We just need non 1 byte aligned address, since ether_type is
 708          * ushort.
 709          */
 710         if ((uintptr_t)mp->b_rptr & 1)
 711                 return (B_FALSE);
 712 
 713         type = ((struct ether_header *)(uintptr_t)mp->b_rptr)->ether_type;
 714         if (type == htons(ETHERTYPE_VLAN)) {
 715                 if (MBLKL(mp) < (sizeof (struct ether_vlan_header) +
 716                     sizeof (ipha_t)))
 717                         return (B_FALSE);
 718                 type = ((struct ether_vlan_header *) \
 719                     (uintptr_t)mp->b_rptr)->ether_type;
 720                 pktinfo->mac_hlen = sizeof (struct ether_vlan_header);
 721         } else {
 722                 pktinfo->mac_hlen = sizeof (struct ether_header);
 723         }
 724         pktinfo->etype = type;
 725 
 726         if (pktinfo->etype == htons(ETHERTYPE_IP)) {
 727                 uchar_t *ip_off = mp->b_rptr + pktinfo->mac_hlen;
 728 
 729                 pktinfo->ip_hlen = IPH_HDR_LENGTH((uintptr_t)ip_off);
 730                 pktinfo->l4_proto =
 731                     ((ipha_t *)(uintptr_t)ip_off)->ipha_protocol;
 732 
 733                 /* IP header not aligned to quadward boundary? */
 734                 if ((unsigned long)(ip_off + pktinfo->ip_hlen) % 8 != 0)
 735                         return (B_FALSE);
 736         }
 737 
 738         return (B_TRUE);
 739 }
 740 
 741 static void
 742 unm_update_pkt_info(char *ptr, pktinfo_t *pktinfo)
 743 {
 744         ushort_t        type;
 745 
 746         type = ((struct ether_header *)(uintptr_t)ptr)->ether_type;
 747         if (type == htons(ETHERTYPE_VLAN)) {
 748                 type = ((struct ether_vlan_header *)(uintptr_t)ptr)->ether_type;
 749                 pktinfo->mac_hlen = sizeof (struct ether_vlan_header);
 750         } else {
 751                 pktinfo->mac_hlen = sizeof (struct ether_header);
 752         }
 753         pktinfo->etype = type;
 754 
 755         if (pktinfo->etype == htons(ETHERTYPE_IP)) {
 756                 char *ipp = ptr + pktinfo->mac_hlen;
 757 
 758                 pktinfo->ip_hlen = IPH_HDR_LENGTH((uintptr_t)ipp);
 759                 pktinfo->l4_proto = ((ipha_t *)(uintptr_t)ipp)->ipha_protocol;
 760         }
 761 }
 762 
 763 static boolean_t
 764 unm_send_copy(struct unm_adapter_s *adapter, mblk_t *mp, pktinfo_t *pktinfo)
 765 {
 766         hardware_context *hw;
 767         u32                             producer = 0;
 768         cmdDescType0_t                  *hwdesc;
 769         struct unm_cmd_buffer           *pbuf = NULL;
 770         u32                             mblen;
 771         int                             no_of_desc = 1;
 772         int                             MaxTxDescCount;
 773         mblk_t                          *bp;
 774         char                            *txb;
 775 
 776         hw = &adapter->ahw;
 777         MaxTxDescCount = adapter->MaxTxDescCount;
 778 
 779         UNM_SPIN_LOCK(&adapter->tx_lock);
 780         membar_enter();
 781 
 782         if (find_diff_among(adapter->cmdProducer, adapter->lastCmdConsumer,
 783             MaxTxDescCount) <= 2) {
 784                 adapter->stats.outofcmddesc++;
 785                 adapter->resched_needed = 1;
 786                 membar_exit();
 787                 UNM_SPIN_UNLOCK(&adapter->tx_lock);
 788                 return (B_FALSE);
 789         }
 790         adapter->freecmds -= no_of_desc;
 791 
 792         producer = adapter->cmdProducer;
 793 
 794         adapter->cmdProducer = get_index_range(adapter->cmdProducer,
 795             MaxTxDescCount, no_of_desc);
 796 
 797         hwdesc = &hw->cmdDescHead[producer];
 798         (void) memset(hwdesc, 0, sizeof (cmdDescType0_t));
 799         pbuf = &adapter->cmd_buf_arr[producer];
 800 
 801         pbuf->msg = NULL;
 802         pbuf->head = NULL;
 803         pbuf->tail = NULL;
 804 
 805         txb = pbuf->dma_area.vaddr;
 806 
 807         for (bp = mp; bp != NULL; bp = bp->b_cont) {
 808                 if ((mblen = MBLKL(bp)) == 0)
 809                         continue;
 810                 bcopy(bp->b_rptr, txb, mblen);
 811                 txb += mblen;
 812         }
 813 
 814         /*
 815          * Determine metadata if not previously done due to fragmented mblk.
 816          */
 817         if (pktinfo->etype == 0)
 818                 unm_update_pkt_info(pbuf->dma_area.vaddr, pktinfo);
 819 
 820         (void) ddi_dma_sync(pbuf->dma_area.dma_hdl,
 821             0, pktinfo->total_len, DDI_DMA_SYNC_FORDEV);
 822 
 823         /* hwdesc->u1.s1.tcpHdrOffset = 0; */
 824         /* hwdesc->mss = 0; */
 825         hwdesc->u1.s1.opcode = TX_ETHER_PKT;
 826         hwdesc->u3.s1.port = adapter->portnum;
 827         hwdesc->u3.s1.ctx_id = adapter->portnum;
 828 
 829         hwdesc->u6.s1.buffer1Length = pktinfo->total_len;
 830         hwdesc->u5.AddrBuffer1 = pbuf->dma_area.dma_addr;
 831         hwdesc->u1.s1.numOfBuffers = 1;
 832         hwdesc->u1.s1.totalLength = pktinfo->total_len;
 833 
 834         unm_tx_csum(hwdesc, mp, pktinfo);
 835 
 836         unm_desc_dma_sync(hw->cmd_desc_dma_handle,
 837             producer,
 838             no_of_desc,
 839             MaxTxDescCount,
 840             sizeof (cmdDescType0_t),
 841             DDI_DMA_SYNC_FORDEV);
 842 
 843         hw->cmdProducer = adapter->cmdProducer;
 844         unm_nic_update_cmd_producer(adapter, adapter->cmdProducer);
 845 
 846         adapter->stats.txbytes += pktinfo->total_len;
 847         adapter->stats.xmitfinished++;
 848         adapter->stats.txcopyed++;
 849         UNM_SPIN_UNLOCK(&adapter->tx_lock);
 850 
 851         freemsg(mp);
 852         return (B_TRUE);
 853 }
 854 
 855 /* Should be called with adapter->tx_lock held. */
 856 static void
 857 unm_return_dma_handle(unm_adapter *adapter, unm_dmah_node_t *head,
 858     unm_dmah_node_t *tail, uint32_t num)
 859 {
 860         ASSERT(tail != NULL);
 861         tail->next = adapter->dmahdl_pool;
 862         adapter->dmahdl_pool = head;
 863         adapter->freehdls += num;
 864 }
 865 
 866 static unm_dmah_node_t *
 867 unm_reserve_dma_handle(unm_adapter* adapter)
 868 {
 869         unm_dmah_node_t *dmah = NULL;
 870 
 871         dmah = adapter->dmahdl_pool;
 872         if (dmah != NULL) {
 873                 adapter->dmahdl_pool = dmah->next;
 874                 dmah->next = NULL;
 875                 adapter->freehdls--;
 876                 membar_exit();
 877         }
 878 
 879         return (dmah);
 880 }
 881 
 882 static boolean_t
 883 unm_send_mapped(struct unm_adapter_s *adapter, mblk_t *mp, pktinfo_t *pktinfo)
 884 {
 885         hardware_context                *hw;
 886         u32                             producer = 0;
 887         u32                             saved_producer = 0;
 888         cmdDescType0_t                  *hwdesc;
 889         struct unm_cmd_buffer           *pbuf = NULL;
 890         int                             no_of_desc;
 891         int                             k;
 892         int                             MaxTxDescCount;
 893         mblk_t                          *bp;
 894 
 895         unm_dmah_node_t *dmah, *head = NULL, *tail = NULL, *hdlp;
 896         ddi_dma_cookie_t cookie[MAX_COOKIES_PER_CMD + 1];
 897         int ret, i;
 898         uint32_t hdl_reserved = 0;
 899         uint32_t mblen;
 900         uint32_t ncookies, index = 0, total_cookies = 0;
 901 
 902         MaxTxDescCount = adapter->MaxTxDescCount;
 903 
 904         UNM_SPIN_LOCK(&adapter->tx_lock);
 905 
 906         /* bind all the mblks of the packet first */
 907         for (bp = mp; bp != NULL; bp = bp->b_cont) {
 908                 mblen = MBLKL(bp);
 909                 if (mblen == 0)
 910                         continue;
 911 
 912                 dmah = unm_reserve_dma_handle(adapter);
 913                 if (dmah == NULL) {
 914                         adapter->stats.outoftxdmahdl++;
 915                         goto err_map;
 916                 }
 917 
 918                 ret = ddi_dma_addr_bind_handle(dmah->dmahdl,
 919                     NULL, (caddr_t)bp->b_rptr, mblen,
 920                     DDI_DMA_STREAMING | DDI_DMA_WRITE,
 921                     DDI_DMA_DONTWAIT, NULL, &cookie[index], &ncookies);
 922 
 923                 if (ret != DDI_DMA_MAPPED)
 924                         goto err_map;
 925 
 926                 if (tail == NULL) {
 927                         head = tail = dmah;
 928                 } else {
 929                         tail->next = dmah;
 930                         tail = dmah;
 931                 }
 932                 hdl_reserved++;
 933 
 934                 total_cookies += ncookies;
 935                 if (total_cookies > MAX_COOKIES_PER_CMD) {
 936                         dmah = NULL;
 937                         goto err_map;
 938                 }
 939 
 940                 if (index == 0) {
 941                         size_t  hsize = cookie[0].dmac_size;
 942 
 943                         /*
 944                          * For TCP/UDP packets with checksum offload,
 945                          * MAC/IP headers need to be contiguous. Otherwise,
 946                          * there must be at least 16 bytes in the first
 947                          * descriptor.
 948                          */
 949                         if ((pktinfo->l4_proto == IPPROTO_TCP) ||
 950                             (pktinfo->l4_proto == IPPROTO_UDP)) {
 951                                 if (hsize < (pktinfo->mac_hlen +
 952                                     pktinfo->ip_hlen)) {
 953                                         dmah = NULL;
 954                                         goto err_map;
 955                                 }
 956                         } else {
 957                                 if (hsize < 16) {
 958                                         dmah = NULL;
 959                                         goto err_map;
 960                                 }
 961                         }
 962                 }
 963 
 964                 index++;
 965                 ncookies--;
 966                 for (i = 0; i < ncookies; i++, index++)
 967                         ddi_dma_nextcookie(dmah->dmahdl, &cookie[index]);
 968         }
 969 
 970         dmah = NULL;
 971         hw = &adapter->ahw;
 972         no_of_desc = (total_cookies + 3) >> 2;
 973 
 974         membar_enter();
 975         if (find_diff_among(adapter->cmdProducer, adapter->lastCmdConsumer,
 976             MaxTxDescCount) < no_of_desc+2) {
 977                 /*
 978                  * If we are going to be trying the copy path, no point
 979                  * scheduling an upcall when Tx resources are freed.
 980                  */
 981                 if (pktinfo->total_len > adapter->maxmtu) {
 982                         adapter->stats.outofcmddesc++;
 983                         adapter->resched_needed = 1;
 984                 }
 985                 membar_exit();
 986                 goto err_alloc_desc;
 987         }
 988         adapter->freecmds -= no_of_desc;
 989 
 990         /* Copy the descriptors into the hardware    */
 991         producer = adapter->cmdProducer;
 992         saved_producer = producer;
 993         hwdesc = &hw->cmdDescHead[producer];
 994         (void) memset(hwdesc, 0, sizeof (cmdDescType0_t));
 995         pbuf = &adapter->cmd_buf_arr[producer];
 996 
 997         pbuf->msg = mp;
 998         pbuf->head = head;
 999         pbuf->tail = tail;
1000 
1001         hwdesc->u1.s1.numOfBuffers = total_cookies;
1002         hwdesc->u1.s1.opcode = TX_ETHER_PKT;
1003         hwdesc->u3.s1.port = adapter->portnum;
1004         /* hwdesc->u1.s1.tcpHdrOffset = 0; */
1005         /* hwdesc->mss = 0; */
1006         hwdesc->u3.s1.ctx_id = adapter->portnum;
1007         hwdesc->u1.s1.totalLength = pktinfo->total_len;
1008         unm_tx_csum(hwdesc, mp, pktinfo);
1009 
1010         for (i = k = 0; i < total_cookies; i++) {
1011                 if (k == 4) {
1012                         /* Move to the next descriptor */
1013                         k = 0;
1014                         producer = get_next_index(producer, MaxTxDescCount);
1015                         hwdesc = &hw->cmdDescHead[producer];
1016                         (void) memset(hwdesc, 0, sizeof (cmdDescType0_t));
1017                 }
1018 
1019                 switch (k) {
1020                 case 0:
1021                         hwdesc->u6.s1.buffer1Length = cookie[i].dmac_size;
1022                         hwdesc->u5.AddrBuffer1 = cookie[i].dmac_laddress;
1023                         break;
1024                 case 1:
1025                         hwdesc->u6.s1.buffer2Length = cookie[i].dmac_size;
1026                         hwdesc->u2.AddrBuffer2 = cookie[i].dmac_laddress;
1027                         break;
1028                 case 2:
1029                         hwdesc->u6.s1.buffer3Length = cookie[i].dmac_size;
1030                         hwdesc->u4.AddrBuffer3 = cookie[i].dmac_laddress;
1031                         break;
1032                 case 3:
1033                         hwdesc->u6.s1.buffer4Length = cookie[i].dmac_size;
1034                         hwdesc->u7.AddrBuffer4 = cookie[i].dmac_laddress;
1035                         break;
1036                 }
1037                 k++;
1038         }
1039 
1040         unm_desc_dma_sync(hw->cmd_desc_dma_handle, saved_producer, no_of_desc,
1041             MaxTxDescCount, sizeof (cmdDescType0_t), DDI_DMA_SYNC_FORDEV);
1042 
1043         adapter->cmdProducer = get_next_index(producer, MaxTxDescCount);
1044         hw->cmdProducer = adapter->cmdProducer;
1045         unm_nic_update_cmd_producer(adapter, adapter->cmdProducer);
1046 
1047         adapter->stats.txbytes += pktinfo->total_len;
1048         adapter->stats.xmitfinished++;
1049         adapter->stats.txmapped++;
1050         UNM_SPIN_UNLOCK(&adapter->tx_lock);
1051         return (B_TRUE);
1052 
1053 err_alloc_desc:
1054 err_map:
1055 
1056         hdlp = head;
1057         while (hdlp != NULL) {
1058                 (void) ddi_dma_unbind_handle(hdlp->dmahdl);
1059                 hdlp = hdlp->next;
1060         }
1061 
1062         /*
1063          * add the reserved but bind failed one to the list to be returned
1064          */
1065         if (dmah != NULL) {
1066                 if (tail == NULL)
1067                         head = tail = dmah;
1068                 else {
1069                         tail->next = dmah;
1070                         tail = dmah;
1071                 }
1072                 hdl_reserved++;
1073         }
1074 
1075         if (head != NULL)
1076                 unm_return_dma_handle(adapter, head, tail, hdl_reserved);
1077 
1078         UNM_SPIN_UNLOCK(&adapter->tx_lock);
1079         return (B_FALSE);
1080 }
1081 
1082 static boolean_t
1083 unm_nic_xmit_frame(unm_adapter *adapter, mblk_t *mp)
1084 {
1085         pktinfo_t       pktinfo;
1086         boolean_t       status = B_FALSE, send_mapped;
1087 
1088         adapter->stats.xmitcalled++;
1089 
1090         send_mapped = unm_get_pkt_info(mp, &pktinfo);
1091 
1092         if (pktinfo.total_len <= adapter->tx_bcopy_threshold ||
1093             pktinfo.mblk_no >= MAX_COOKIES_PER_CMD)
1094                 send_mapped = B_FALSE;
1095 
1096         if (send_mapped == B_TRUE)
1097                 status = unm_send_mapped(adapter, mp, &pktinfo);
1098 
1099         if (status != B_TRUE) {
1100                 if (pktinfo.total_len <= adapter->maxmtu)
1101                         return (unm_send_copy(adapter, mp, &pktinfo));
1102 
1103                 /* message too large */
1104                 freemsg(mp);
1105                 adapter->stats.txdropped++;
1106                 status = B_TRUE;
1107         }
1108 
1109         return (status);
1110 }
1111 
1112 static int
1113 unm_nic_check_temp(struct unm_adapter_s *adapter)
1114 {
1115         uint32_t temp, temp_state, temp_val;
1116         int rv = 0;
1117 
1118         if ((adapter->ahw.revision_id == NX_P3_A2) ||
1119             (adapter->ahw.revision_id == NX_P3_A0))
1120                 return (0);
1121 
1122         temp = adapter->unm_nic_pci_read_normalize(adapter, CRB_TEMP_STATE);
1123 
1124         temp_state = nx_get_temp_state(temp);
1125         temp_val = nx_get_temp_val(temp);
1126 
1127         if (temp_state == NX_TEMP_PANIC) {
1128                 cmn_err(CE_WARN, "%s: Device temperature %d C exceeds "
1129                     "maximum allowed, device has been shut down\n",
1130                     unm_nic_driver_name, temp_val);
1131                 rv = 1;
1132         } else if (temp_state == NX_TEMP_WARN) {
1133                 if (adapter->temp == NX_TEMP_NORMAL) {
1134                 cmn_err(CE_WARN, "%s: Device temperature %d C exceeds"
1135                     "operating range. Immediate action needed.\n",
1136                     unm_nic_driver_name, temp_val);
1137                 }
1138         } else {
1139                 if (adapter->temp == NX_TEMP_WARN) {
1140                         cmn_err(CE_WARN, "%s: Device temperature is now %d "
1141                             "degrees C in normal range.\n",
1142                             unm_nic_driver_name, temp_val);
1143                 }
1144         }
1145 
1146         adapter->temp = temp_state;
1147         return (rv);
1148 }
1149 
1150 static void
1151 unm_watchdog(unsigned long v)
1152 {
1153         unm_adapter *adapter = (unm_adapter *)v;
1154 
1155         if ((adapter->portnum == 0) && unm_nic_check_temp(adapter)) {
1156                 /*
1157                  * We return without turning on the netdev queue as there
1158                  * was an overheated device
1159                  */
1160                 return;
1161         }
1162 
1163         unm_nic_handle_phy_intr(adapter);
1164 
1165         /*
1166          * This function schedules a call for itself.
1167          */
1168         adapter->watchdog_timer = timeout((void (*)(void *))&unm_watchdog,
1169             (void *)adapter, 2 * drv_usectohz(1000000));
1170 
1171 }
1172 
1173 static void unm_nic_clear_stats(unm_adapter *adapter)
1174 {
1175         (void) memset(&adapter->stats, 0, sizeof (adapter->stats));
1176 }
1177 
1178 static void
1179 unm_nic_poll(unm_adapter *adapter)
1180 {
1181         int     work_done, tx_complete;
1182 
1183         adapter->stats.polled++;
1184 
1185 loop:
1186         tx_complete = unm_process_cmd_ring(adapter);
1187         work_done = unm_process_rcv_ring(adapter, NX_RX_MAXBUFS);
1188         if ((!tx_complete) || (!(work_done < NX_RX_MAXBUFS)))
1189                 goto loop;
1190 
1191         UNM_READ_LOCK(&adapter->adapter_lock);
1192         unm_nic_enable_int(adapter);
1193         UNM_READ_UNLOCK(&adapter->adapter_lock);
1194 }
1195 
1196 /* ARGSUSED */
1197 uint_t
1198 unm_intr(caddr_t data, caddr_t arg)
1199 {
1200         unm_adapter     *adapter = (unm_adapter *)(uintptr_t)data;
1201 
1202         if (unm_nic_clear_int(adapter))
1203                 return (DDI_INTR_UNCLAIMED);
1204 
1205         unm_nic_poll(adapter);
1206         return (DDI_INTR_CLAIMED);
1207 }
1208 
1209 /*
1210  * This is invoked from receive isr. Due to the single threaded nature
1211  * of the invocation, pool_lock acquisition is not neccesary to protect
1212  * pool_list.
1213  */
1214 static void
1215 unm_free_rx_buffer(unm_rcv_desc_ctx_t *rcv_desc, unm_rx_buffer_t *rx_buffer)
1216 {
1217         /* mutex_enter(rcv_desc->pool_lock); */
1218         rx_buffer->next = rcv_desc->pool_list;
1219         rcv_desc->pool_list = rx_buffer;
1220         rcv_desc->rx_buf_free++;
1221         /* mutex_exit(rcv_desc->pool_lock); */
1222 }
1223 
1224 /*
1225  * unm_process_rcv() send the received packet to the protocol stack.
1226  */
1227 static mblk_t *
1228 unm_process_rcv(unm_adapter *adapter, statusDesc_t *desc)
1229 {
1230         unm_recv_context_t      *recv_ctx = &(adapter->recv_ctx[0]);
1231         unm_rx_buffer_t         *rx_buffer;
1232         mblk_t *mp;
1233         u32                     desc_ctx = desc->u1.s1.type;
1234         unm_rcv_desc_ctx_t      *rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
1235         u32                     pkt_length = desc->u1.s1.totalLength;
1236         int                     poff = desc->u1.s1.pkt_offset;
1237         int                     index, cksum_flags, docopy;
1238         int                     index_lo = desc->u1.s1.referenceHandle_lo;
1239         char                    *vaddr;
1240 
1241         index = ((desc->u1.s1.referenceHandle_hi << 4) | index_lo);
1242 
1243         rx_buffer = index2rxbuf(rcv_desc, index);
1244 
1245         if (rx_buffer == NULL) {
1246                 cmn_err(CE_WARN, "\r\nNULL rx_buffer idx=%d", index);
1247                 return (NULL);
1248         }
1249         vaddr = (char *)rx_buffer->dma_info.vaddr;
1250         if (vaddr == NULL) {
1251                 cmn_err(CE_WARN, "\r\nNULL vaddr");
1252                 return (NULL);
1253         }
1254         rcv_desc->rx_desc_handled++;
1255         rcv_desc->rx_buf_card--;
1256 
1257         (void) ddi_dma_sync(rx_buffer->dma_info.dma_hdl, 0,
1258             pkt_length + poff + (adapter->ahw.cut_through ? 0 :
1259             IP_ALIGNMENT_BYTES), DDI_DMA_SYNC_FORCPU);
1260 
1261         /*
1262          * Copy packet into new allocated message buffer, if pkt_length
1263          * is below copy threshold.
1264          */
1265         docopy = (pkt_length <= adapter->rx_bcopy_threshold) ? 1 : 0;
1266 
1267         /*
1268          * If card is running out of rx buffers, then attempt to allocate
1269          * new mblk so we can feed this rx buffer back to card (we
1270          * _could_ look at what's pending on free and recycle lists).
1271          */
1272         if (rcv_desc->rx_buf_card < NX_RX_THRESHOLD) {
1273                 docopy = 1;
1274                 adapter->stats.rxbufshort++;
1275         }
1276 
1277         if (docopy == 1) {
1278                 if ((mp = allocb(pkt_length + IP_ALIGNMENT_BYTES, 0)) == NULL) {
1279                         adapter->stats.allocbfailed++;
1280                         goto freebuf;
1281                 }
1282 
1283                 mp->b_rptr += IP_ALIGNMENT_BYTES;
1284                 vaddr += poff;
1285                 bcopy(vaddr, mp->b_rptr, pkt_length);
1286                 adapter->stats.rxcopyed++;
1287                 unm_free_rx_buffer(rcv_desc, rx_buffer);
1288         } else {
1289                 mp = (mblk_t *)rx_buffer->mp;
1290                 if (mp == NULL) {
1291                         mp = desballoc(rx_buffer->dma_info.vaddr,
1292                             rcv_desc->dma_size, 0, &rx_buffer->rx_recycle);
1293                         if (mp == NULL) {
1294                                 adapter->stats.desballocfailed++;
1295                                 goto freebuf;
1296                         }
1297                         rx_buffer->mp = mp;
1298                 }
1299                 mp->b_rptr += poff;
1300                 adapter->stats.rxmapped++;
1301         }
1302 
1303         mp->b_wptr = (uchar_t *)((unsigned long)mp->b_rptr + pkt_length);
1304 
1305         if (desc->u1.s1.status == STATUS_CKSUM_OK) {
1306                 adapter->stats.csummed++;
1307                 cksum_flags =
1308                     HCK_FULLCKSUM_OK | HCK_IPV4_HDRCKSUM_OK;
1309         } else {
1310                 cksum_flags = 0;
1311         }
1312         mac_hcksum_set(mp, 0, 0, 0, 0, cksum_flags);
1313 
1314         adapter->stats.no_rcv++;
1315         adapter->stats.rxbytes += pkt_length;
1316         adapter->stats.uphappy++;
1317 
1318         return (mp);
1319 
1320 freebuf:
1321         unm_free_rx_buffer(rcv_desc, rx_buffer);
1322         return (NULL);
1323 }
1324 
1325 /* Process Receive status ring */
1326 static int
1327 unm_process_rcv_ring(unm_adapter *adapter, int max)
1328 {
1329         unm_recv_context_t      *recv_ctx = &(adapter->recv_ctx[0]);
1330         statusDesc_t            *desc_head = recv_ctx->rcvStatusDescHead;
1331         statusDesc_t            *desc = NULL;
1332         uint32_t                consumer, start;
1333         int                     count = 0, ring;
1334         mblk_t *mp;
1335 
1336         start = consumer = recv_ctx->statusRxConsumer;
1337 
1338         unm_desc_dma_sync(recv_ctx->status_desc_dma_handle, start, max,
1339             adapter->MaxRxDescCount, sizeof (statusDesc_t),
1340             DDI_DMA_SYNC_FORCPU);
1341 
1342         while (count < max) {
1343                 desc = &desc_head[consumer];
1344                 if (!(desc->u1.s1.owner & STATUS_OWNER_HOST))
1345                         break;
1346 
1347                 mp = unm_process_rcv(adapter, desc);
1348                 desc->u1.s1.owner = STATUS_OWNER_PHANTOM;
1349 
1350                 consumer = (consumer + 1) % adapter->MaxRxDescCount;
1351                 count++;
1352                 if (mp != NULL)
1353                         mac_rx(adapter->mach, NULL, mp);
1354         }
1355 
1356         for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1357                 if (recv_ctx->rcv_desc[ring].rx_desc_handled > 0)
1358                         unm_post_rx_buffers_nodb(adapter, ring);
1359         }
1360 
1361         if (count) {
1362                 unm_desc_dma_sync(recv_ctx->status_desc_dma_handle, start,
1363                     count, adapter->MaxRxDescCount, sizeof (statusDesc_t),
1364                     DDI_DMA_SYNC_FORDEV);
1365 
1366                 /* update the consumer index in phantom */
1367                 recv_ctx->statusRxConsumer = consumer;
1368 
1369                 UNM_READ_LOCK(&adapter->adapter_lock);
1370                 adapter->unm_nic_hw_write_wx(adapter,
1371                     recv_ctx->host_sds_consumer, &consumer, 4);
1372                 UNM_READ_UNLOCK(&adapter->adapter_lock);
1373         }
1374 
1375         return (count);
1376 }
1377 
1378 /* Process Command status ring */
1379 static int
1380 unm_process_cmd_ring(struct unm_adapter_s *adapter)
1381 {
1382         u32                     last_consumer;
1383         u32                     consumer;
1384         int                     count = 0;
1385         struct unm_cmd_buffer   *buffer;
1386         int                     done;
1387         unm_dmah_node_t *dmah, *head = NULL, *tail = NULL;
1388         uint32_t        free_hdls = 0;
1389 
1390         (void) ddi_dma_sync(adapter->ctxDesc_dma_handle, sizeof (RingContext),
1391             sizeof (uint32_t), DDI_DMA_SYNC_FORCPU);
1392 
1393         last_consumer = adapter->lastCmdConsumer;
1394         consumer = *(adapter->cmdConsumer);
1395 
1396         while (last_consumer != consumer) {
1397                 buffer = &adapter->cmd_buf_arr[last_consumer];
1398                 if (buffer->head != NULL) {
1399                         dmah = buffer->head;
1400                         while (dmah != NULL) {
1401                                 (void) ddi_dma_unbind_handle(dmah->dmahdl);
1402                                 dmah = dmah->next;
1403                                 free_hdls++;
1404                         }
1405 
1406                         if (head == NULL) {
1407                                 head = buffer->head;
1408                                 tail = buffer->tail;
1409                         } else {
1410                                 tail->next = buffer->head;
1411                                 tail = buffer->tail;
1412                         }
1413 
1414                         buffer->head = NULL;
1415                         buffer->tail = NULL;
1416 
1417                         if (buffer->msg != NULL) {
1418                                 freemsg(buffer->msg);
1419                                 buffer->msg = NULL;
1420                         }
1421                 }
1422 
1423                 last_consumer = get_next_index(last_consumer,
1424                     adapter->MaxTxDescCount);
1425                 if (++count > NX_MAX_TXCOMPS)
1426                         break;
1427         }
1428 
1429         if (count) {
1430                 int     doresched;
1431 
1432                 UNM_SPIN_LOCK(&adapter->tx_lock);
1433                 adapter->lastCmdConsumer = last_consumer;
1434                 adapter->freecmds += count;
1435                 membar_exit();
1436 
1437                 doresched = adapter->resched_needed;
1438                 if (doresched)
1439                         adapter->resched_needed = 0;
1440 
1441                 if (head != NULL)
1442                         unm_return_dma_handle(adapter, head, tail, free_hdls);
1443 
1444                 UNM_SPIN_UNLOCK(&adapter->tx_lock);
1445 
1446                 if (doresched)
1447                         mac_tx_update(adapter->mach);
1448         }
1449 
1450         (void) ddi_dma_sync(adapter->ctxDesc_dma_handle, sizeof (RingContext),
1451             sizeof (uint32_t), DDI_DMA_SYNC_FORCPU);
1452 
1453         consumer = *(adapter->cmdConsumer);
1454         done = (adapter->lastCmdConsumer == consumer);
1455 
1456         return (done);
1457 }
1458 
1459 /*
1460  * This is invoked from receive isr, and at initialization time when no
1461  * rx buffers have been posted to card. Due to the single threaded nature
1462  * of the invocation, pool_lock acquisition is not neccesary to protect
1463  * pool_list.
1464  */
1465 static unm_rx_buffer_t *
1466 unm_reserve_rx_buffer(unm_rcv_desc_ctx_t *rcv_desc)
1467 {
1468         unm_rx_buffer_t *rx_buffer = NULL;
1469 
1470         /* mutex_enter(rcv_desc->pool_lock); */
1471         if (rcv_desc->rx_buf_free) {
1472                 rx_buffer = rcv_desc->pool_list;
1473                 rcv_desc->pool_list = rx_buffer->next;
1474                 rx_buffer->next = NULL;
1475                 rcv_desc->rx_buf_free--;
1476         } else {
1477                 mutex_enter(rcv_desc->recycle_lock);
1478 
1479                 if (rcv_desc->rx_buf_recycle) {
1480                         rcv_desc->pool_list = rcv_desc->recycle_list;
1481                         rcv_desc->recycle_list = NULL;
1482                         rcv_desc->rx_buf_free += rcv_desc->rx_buf_recycle;
1483                         rcv_desc->rx_buf_recycle = 0;
1484 
1485                         rx_buffer = rcv_desc->pool_list;
1486                         rcv_desc->pool_list = rx_buffer->next;
1487                         rx_buffer->next = NULL;
1488                         rcv_desc->rx_buf_free--;
1489                 }
1490 
1491                 mutex_exit(rcv_desc->recycle_lock);
1492         }
1493 
1494         /* mutex_exit(rcv_desc->pool_lock); */
1495         return (rx_buffer);
1496 }
1497 
1498 static void
1499 post_rx_doorbell(struct unm_adapter_s *adapter, uint32_t ringid, int count)
1500 {
1501 #define UNM_RCV_PEG_DB_ID       2
1502 #define UNM_RCV_PRODUCER_OFFSET 0
1503         ctx_msg msg = {0};
1504 
1505         /*
1506          * Write a doorbell msg to tell phanmon of change in
1507          * receive ring producer
1508          */
1509         msg.PegId = UNM_RCV_PEG_DB_ID;
1510         msg.privId = 1;
1511         msg.Count = count;
1512         msg.CtxId = adapter->portnum;
1513         msg.Opcode = UNM_RCV_PRODUCER(ringid);
1514         dbwritel(*((__uint32_t *)&msg),
1515             (void *)(DB_NORMALIZE(adapter, UNM_RCV_PRODUCER_OFFSET)));
1516 }
1517 
1518 static int
1519 unm_post_rx_buffers(struct unm_adapter_s *adapter, uint32_t ringid)
1520 {
1521         unm_recv_context_t      *recv_ctx = &(adapter->recv_ctx[0]);
1522         unm_rcv_desc_ctx_t      *rcv_desc = &recv_ctx->rcv_desc[ringid];
1523         unm_rx_buffer_t         *rx_buffer;
1524         rcvDesc_t               *pdesc;
1525         int                     count;
1526 
1527         for (count = 0; count < rcv_desc->MaxRxDescCount; count++) {
1528                 rx_buffer = unm_reserve_rx_buffer(rcv_desc);
1529                 if (rx_buffer != NULL) {
1530                         pdesc = &rcv_desc->desc_head[count];
1531                         pdesc->referenceHandle = rxbuf2index(rcv_desc,
1532                             rx_buffer);
1533                         pdesc->flags = ringid;
1534                         pdesc->bufferLength = rcv_desc->dma_size;
1535                         pdesc->AddrBuffer = rx_buffer->dma_info.dma_addr;
1536                 }
1537                 else
1538                         return (DDI_FAILURE);
1539         }
1540 
1541         rcv_desc->producer = count % rcv_desc->MaxRxDescCount;
1542         count--;
1543         unm_desc_dma_sync(rcv_desc->rx_desc_dma_handle,
1544             0,          /* start */
1545             count,      /* count */
1546             count,      /* range */
1547             sizeof (rcvDesc_t), /* unit_size */
1548             DDI_DMA_SYNC_FORDEV);       /* direction */
1549 
1550         rcv_desc->rx_buf_card = rcv_desc->MaxRxDescCount;
1551         UNM_READ_LOCK(&adapter->adapter_lock);
1552         adapter->unm_nic_hw_write_wx(adapter, rcv_desc->host_rx_producer,
1553             &count, 4);
1554         if (adapter->fw_major < 4)
1555                 post_rx_doorbell(adapter, ringid, count);
1556         UNM_READ_UNLOCK(&adapter->adapter_lock);
1557 
1558         return (DDI_SUCCESS);
1559 }
1560 
1561 static void
1562 unm_post_rx_buffers_nodb(struct unm_adapter_s *adapter,
1563     uint32_t ringid)
1564 {
1565         unm_recv_context_t      *recv_ctx = &(adapter->recv_ctx[0]);
1566         unm_rcv_desc_ctx_t      *rcv_desc = &recv_ctx->rcv_desc[ringid];
1567         struct unm_rx_buffer    *rx_buffer;
1568         rcvDesc_t               *pdesc;
1569         int                     count, producer = rcv_desc->producer;
1570         int                     last_producer = producer;
1571 
1572         for (count = 0; count < rcv_desc->rx_desc_handled; count++) {
1573                 rx_buffer = unm_reserve_rx_buffer(rcv_desc);
1574                 if (rx_buffer != NULL) {
1575                         pdesc = &rcv_desc->desc_head[producer];
1576                         pdesc->referenceHandle = rxbuf2index(rcv_desc,
1577                             rx_buffer);
1578                         pdesc->flags = ringid;
1579                         pdesc->bufferLength = rcv_desc->dma_size;
1580                         pdesc->AddrBuffer = rx_buffer->dma_info.dma_addr;
1581                 } else {
1582                         adapter->stats.outofrxbuf++;
1583                         break;
1584                 }
1585                 producer = get_next_index(producer, rcv_desc->MaxRxDescCount);
1586         }
1587 
1588         /* if we did allocate buffers, then write the count to Phantom */
1589         if (count) {
1590                 /* Sync rx ring, considering case for wrap around */
1591                 unm_desc_dma_sync(rcv_desc->rx_desc_dma_handle, last_producer,
1592                     count, rcv_desc->MaxRxDescCount, sizeof (rcvDesc_t),
1593                     DDI_DMA_SYNC_FORDEV);
1594 
1595                 rcv_desc->producer = producer;
1596                 rcv_desc->rx_desc_handled -= count;
1597                 rcv_desc->rx_buf_card += count;
1598 
1599                 producer = (producer - 1) % rcv_desc->MaxRxDescCount;
1600                 UNM_READ_LOCK(&adapter->adapter_lock);
1601                 adapter->unm_nic_hw_write_wx(adapter,
1602                     rcv_desc->host_rx_producer, &producer, 4);
1603                 UNM_READ_UNLOCK(&adapter->adapter_lock);
1604         }
1605 }
1606 
1607 int
1608 unm_nic_fill_statistics_128M(struct unm_adapter_s *adapter,
1609                             struct unm_statistics *unm_stats)
1610 {
1611         void *addr;
1612         if (adapter->ahw.board_type == UNM_NIC_XGBE) {
1613                 UNM_WRITE_LOCK(&adapter->adapter_lock);
1614                 unm_nic_pci_change_crbwindow_128M(adapter, 0);
1615 
1616                 /* LINTED: E_FALSE_LOGICAL_EXPR */
1617                 UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_TX_BYTE_CNT,
1618                     &(unm_stats->tx_bytes));
1619                 /* LINTED: E_FALSE_LOGICAL_EXPR */
1620                 UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_TX_FRAME_CNT,
1621                     &(unm_stats->tx_packets));
1622                 /* LINTED: E_FALSE_LOGICAL_EXPR */
1623                 UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_RX_BYTE_CNT,
1624                     &(unm_stats->rx_bytes));
1625                 /* LINTED: E_FALSE_LOGICAL_EXPR */
1626                 UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_RX_FRAME_CNT,
1627                     &(unm_stats->rx_packets));
1628                 /* LINTED: E_FALSE_LOGICAL_EXPR */
1629                 UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_AGGR_ERROR_CNT,
1630                     &(unm_stats->rx_errors));
1631                 /* LINTED: E_FALSE_LOGICAL_EXPR */
1632                 UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_CRC_ERROR_CNT,
1633                     &(unm_stats->rx_CRC_errors));
1634                 /* LINTED: E_FALSE_LOGICAL_EXPR */
1635                 UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_OVERSIZE_FRAME_ERR,
1636                     &(unm_stats->rx_long_length_error));
1637                 /* LINTED: E_FALSE_LOGICAL_EXPR */
1638                 UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_UNDERSIZE_FRAME_ERR,
1639                     &(unm_stats->rx_short_length_error));
1640 
1641                 /*
1642                  * For reading rx_MAC_error bit different procedure
1643                  * UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_TEST_MUX_CTL, 0x15);
1644                  * UNM_NIC_LOCKED_READ_REG((UNM_CRB_NIU + 0xC0), &temp);
1645                  * unm_stats->rx_MAC_errors = temp & 0xff;
1646                  */
1647 
1648                 unm_nic_pci_change_crbwindow_128M(adapter, 1);
1649                 UNM_WRITE_UNLOCK(&adapter->adapter_lock);
1650         } else {
1651                 UNM_SPIN_LOCK_ISR(&adapter->tx_lock);
1652                 unm_stats->tx_bytes = adapter->stats.txbytes;
1653                 unm_stats->tx_packets = adapter->stats.xmitedframes +
1654                     adapter->stats.xmitfinished;
1655                 unm_stats->rx_bytes = adapter->stats.rxbytes;
1656                 unm_stats->rx_packets = adapter->stats.no_rcv;
1657                 unm_stats->rx_errors = adapter->stats.rcvdbadmsg;
1658                 unm_stats->tx_errors = adapter->stats.nocmddescriptor;
1659                 unm_stats->rx_short_length_error = adapter->stats.uplcong;
1660                 unm_stats->rx_long_length_error = adapter->stats.uphcong;
1661                 unm_stats->rx_CRC_errors = 0;
1662                 unm_stats->rx_MAC_errors = 0;
1663                 UNM_SPIN_UNLOCK_ISR(&adapter->tx_lock);
1664         }
1665         return (0);
1666 }
1667 
1668 int
1669 unm_nic_fill_statistics_2M(struct unm_adapter_s *adapter,
1670     struct unm_statistics *unm_stats)
1671 {
1672         if (adapter->ahw.board_type == UNM_NIC_XGBE) {
1673                 (void) unm_nic_hw_read_wx_2M(adapter, UNM_NIU_XGE_TX_BYTE_CNT,
1674                     &(unm_stats->tx_bytes), 4);
1675                 (void) unm_nic_hw_read_wx_2M(adapter, UNM_NIU_XGE_TX_FRAME_CNT,
1676                     &(unm_stats->tx_packets), 4);
1677                 (void) unm_nic_hw_read_wx_2M(adapter, UNM_NIU_XGE_RX_BYTE_CNT,
1678                     &(unm_stats->rx_bytes), 4);
1679                 (void) unm_nic_hw_read_wx_2M(adapter, UNM_NIU_XGE_RX_FRAME_CNT,
1680                     &(unm_stats->rx_packets), 4);
1681                 (void) unm_nic_hw_read_wx_2M(adapter,
1682                     UNM_NIU_XGE_AGGR_ERROR_CNT, &(unm_stats->rx_errors), 4);
1683                 (void) unm_nic_hw_read_wx_2M(adapter, UNM_NIU_XGE_CRC_ERROR_CNT,
1684                     &(unm_stats->rx_CRC_errors), 4);
1685                 (void) unm_nic_hw_read_wx_2M(adapter,
1686                     UNM_NIU_XGE_OVERSIZE_FRAME_ERR,
1687                     &(unm_stats->rx_long_length_error), 4);
1688                 (void) unm_nic_hw_read_wx_2M(adapter,
1689                     UNM_NIU_XGE_UNDERSIZE_FRAME_ERR,
1690                     &(unm_stats->rx_short_length_error), 4);
1691         } else {
1692                 UNM_SPIN_LOCK_ISR(&adapter->tx_lock);
1693                 unm_stats->tx_bytes = adapter->stats.txbytes;
1694                 unm_stats->tx_packets = adapter->stats.xmitedframes +
1695                     adapter->stats.xmitfinished;
1696                 unm_stats->rx_bytes = adapter->stats.rxbytes;
1697                 unm_stats->rx_packets = adapter->stats.no_rcv;
1698                 unm_stats->rx_errors = adapter->stats.rcvdbadmsg;
1699                 unm_stats->tx_errors = adapter->stats.nocmddescriptor;
1700                 unm_stats->rx_short_length_error = adapter->stats.uplcong;
1701                 unm_stats->rx_long_length_error = adapter->stats.uphcong;
1702                 unm_stats->rx_CRC_errors = 0;
1703                 unm_stats->rx_MAC_errors = 0;
1704                 UNM_SPIN_UNLOCK_ISR(&adapter->tx_lock);
1705         }
1706         return (0);
1707 }
1708 
1709 int
1710 unm_nic_clear_statistics_128M(struct unm_adapter_s *adapter)
1711 {
1712         void *addr;
1713         int data = 0;
1714 
1715         UNM_WRITE_LOCK(&adapter->adapter_lock);
1716         unm_nic_pci_change_crbwindow_128M(adapter, 0);
1717 
1718         /* LINTED: E_FALSE_LOGICAL_EXPR */
1719         UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_TX_BYTE_CNT, &data);
1720         /* LINTED: E_FALSE_LOGICAL_EXPR */
1721         UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_TX_FRAME_CNT, &data);
1722         /* LINTED: E_FALSE_LOGICAL_EXPR */
1723         UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_RX_BYTE_CNT, &data);
1724         /* LINTED: E_FALSE_LOGICAL_EXPR */
1725         UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_RX_FRAME_CNT, &data);
1726         /* LINTED: E_FALSE_LOGICAL_EXPR */
1727         UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_AGGR_ERROR_CNT, &data);
1728         /* LINTED: E_FALSE_LOGICAL_EXPR */
1729         UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_CRC_ERROR_CNT, &data);
1730         /* LINTED: E_FALSE_LOGICAL_EXPR */
1731         UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_OVERSIZE_FRAME_ERR, &data);
1732         /* LINTED: E_FALSE_LOGICAL_EXPR */
1733         UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_UNDERSIZE_FRAME_ERR, &data);
1734 
1735         unm_nic_pci_change_crbwindow_128M(adapter, 1);
1736         UNM_WRITE_UNLOCK(&adapter->adapter_lock);
1737         unm_nic_clear_stats(adapter);
1738         return (0);
1739 }
1740 
1741 int
1742 unm_nic_clear_statistics_2M(struct unm_adapter_s *adapter)
1743 {
1744         int data = 0;
1745 
1746         (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_TX_BYTE_CNT,
1747             &data, 4);
1748         (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_TX_FRAME_CNT,
1749             &data, 4);
1750         (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_RX_BYTE_CNT,
1751             &data, 4);
1752         (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_RX_FRAME_CNT,
1753             &data, 4);
1754         (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_AGGR_ERROR_CNT,
1755             &data, 4);
1756         (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_CRC_ERROR_CNT,
1757             &data, 4);
1758         (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_OVERSIZE_FRAME_ERR,
1759             &data, 4);
1760         (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_UNDERSIZE_FRAME_ERR,
1761             &data, 4);
1762         unm_nic_clear_stats(adapter);
1763         return (0);
1764 }
1765 
1766 /*
1767  * unm_nic_ioctl ()    We provide the tcl/phanmon support
1768  * through these ioctls.
1769  */
1770 static void
1771 unm_nic_ioctl(struct unm_adapter_s *adapter, int cmd, queue_t *q, mblk_t *mp)
1772 {
1773         void *ptr;
1774 
1775         switch (cmd) {
1776         case UNM_NIC_CMD:
1777                 (void) unm_nic_do_ioctl(adapter, q, mp);
1778                 break;
1779 
1780         case UNM_NIC_NAME:
1781                 ptr = (void *) mp->b_cont->b_rptr;
1782 
1783                 /*
1784                  * Phanmon checks for "UNM-UNM" string
1785                  * Replace the hardcoded value with appropriate macro
1786                  */
1787                 DPRINTF(-1, (CE_CONT, "UNM_NIC_NAME ioctl executed %d %d\n",
1788                     cmd, __LINE__));
1789                 (void) memcpy(ptr, "UNM-UNM", 10);
1790                 miocack(q, mp, 10, 0);
1791                 break;
1792 
1793         default:
1794                 cmn_err(CE_WARN, "Netxen ioctl cmd %x not supported\n", cmd);
1795 
1796                 miocnak(q, mp, 0, EINVAL);
1797                 break;
1798         }
1799 }
1800 
1801 int
1802 unm_nic_resume(unm_adapter *adapter)
1803 {
1804 
1805         adapter->watchdog_timer = timeout((void (*)(void *))&unm_watchdog,
1806             (void *) adapter, 50000);
1807 
1808         if (adapter->intr_type == DDI_INTR_TYPE_MSI)
1809                 (void) ddi_intr_block_enable(&adapter->intr_handle, 1);
1810         else
1811                 (void) ddi_intr_enable(adapter->intr_handle);
1812         UNM_READ_LOCK(&adapter->adapter_lock);
1813         unm_nic_enable_int(adapter);
1814         UNM_READ_UNLOCK(&adapter->adapter_lock);
1815 
1816         mac_link_update(adapter->mach, LINK_STATE_UP);
1817 
1818         return (DDI_SUCCESS);
1819 }
1820 
1821 int
1822 unm_nic_suspend(unm_adapter *adapter)
1823 {
1824         mac_link_update(adapter->mach, LINK_STATE_DOWN);
1825 
1826         (void) untimeout(adapter->watchdog_timer);
1827 
1828         UNM_READ_LOCK(&adapter->adapter_lock);
1829         unm_nic_disable_int(adapter);
1830         UNM_READ_UNLOCK(&adapter->adapter_lock);
1831         if (adapter->intr_type == DDI_INTR_TYPE_MSI)
1832                 (void) ddi_intr_block_disable(&adapter->intr_handle, 1);
1833         else
1834                 (void) ddi_intr_disable(adapter->intr_handle);
1835 
1836         return (DDI_SUCCESS);
1837 }
1838 
1839 static int
1840 unm_nic_do_ioctl(unm_adapter *adapter, queue_t *wq, mblk_t *mp)
1841 {
1842         unm_nic_ioctl_data_t            data;
1843         struct unm_nic_ioctl_data       *up_data;
1844         ddi_acc_handle_t                conf_handle;
1845         int                             retval = 0;
1846         uint64_t                        efuse_chip_id = 0;
1847         char                            *ptr1;
1848         short                           *ptr2;
1849         int                             *ptr4;
1850 
1851         up_data = (struct unm_nic_ioctl_data *)(mp->b_cont->b_rptr);
1852         (void) memcpy(&data, (void **)(uintptr_t)(mp->b_cont->b_rptr),
1853             sizeof (data));
1854 
1855         /* Shouldn't access beyond legal limits of  "char u[64];" member */
1856         if (data.size > sizeof (data.uabc)) {
1857                 /* evil user tried to crash the kernel */
1858                 cmn_err(CE_WARN, "bad size: %d\n", data.size);
1859                 retval = GLD_BADARG;
1860                 goto error_out;
1861         }
1862 
1863         switch (data.cmd) {
1864         case unm_nic_cmd_pci_read:
1865 
1866                 if ((retval = adapter->unm_nic_hw_read_ioctl(adapter,
1867                     data.off, up_data, data.size))) {
1868                         DPRINTF(-1, (CE_WARN, "%s(%d) unm_nic_hw_read_wx "
1869                     "returned %d\n", __FUNCTION__, __LINE__, retval));
1870 
1871                         retval = data.rv;
1872                         goto error_out;
1873                 }
1874 
1875                 data.rv = 0;
1876                 break;
1877 
1878         case unm_nic_cmd_pci_write:
1879                 if ((data.rv = adapter->unm_nic_hw_write_ioctl(adapter,
1880                     data.off, &(data.uabc), data.size))) {
1881                         DPRINTF(-1, (CE_WARN, "%s(%d) unm_nic_hw_write_wx "
1882                             "returned %d\n", __FUNCTION__,
1883                             __LINE__, data.rv));
1884                         retval = data.rv;
1885                         goto error_out;
1886                 }
1887                 data.size = 0;
1888                 break;
1889 
1890         case unm_nic_cmd_pci_mem_read:
1891                 if ((data.rv = adapter->unm_nic_pci_mem_read(adapter,
1892                     data.off, up_data, data.size))) {
1893                         DPRINTF(-1, (CE_WARN, "%s(%d) unm_nic_pci_mem_read "
1894                             "returned %d\n", __FUNCTION__,
1895                             __LINE__, data.rv));
1896                         retval = data.rv;
1897                         goto error_out;
1898                 }
1899                 data.rv = 0;
1900                 break;
1901 
1902         case unm_nic_cmd_pci_mem_write:
1903                 if ((data.rv = adapter->unm_nic_pci_mem_write(adapter,
1904                     data.off, &(data.uabc), data.size))) {
1905                         DPRINTF(-1, (CE_WARN,
1906                             "%s(%d) unm_nic_cmd_pci_mem_write "
1907                             "returned %d\n",
1908                             __FUNCTION__, __LINE__, data.rv));
1909                         retval = data.rv;
1910                         goto error_out;
1911                 }
1912 
1913                 data.size = 0;
1914                 data.rv = 0;
1915                 break;
1916 
1917         case unm_nic_cmd_pci_config_read:
1918 
1919                 if (adapter->pci_cfg_handle != NULL) {
1920                         conf_handle = adapter->pci_cfg_handle;
1921 
1922                 } else if ((retval = pci_config_setup(adapter->dip,
1923                     &conf_handle)) != DDI_SUCCESS) {
1924                         DPRINTF(-1, (CE_WARN, "!%s: pci_config_setup failed"
1925                             " error:%d\n", unm_nic_driver_name, retval));
1926                         goto error_out;
1927 
1928                 } else
1929                         adapter->pci_cfg_handle = conf_handle;
1930 
1931                 switch (data.size) {
1932                 case 1:
1933                         ptr1 = (char *)up_data;
1934                         *ptr1 = (char)pci_config_get8(conf_handle, data.off);
1935                         break;
1936                 case 2:
1937                         ptr2 = (short *)up_data;
1938                         *ptr2 = (short)pci_config_get16(conf_handle, data.off);
1939                         break;
1940                 case 4:
1941                         ptr4 = (int *)up_data;
1942                         *ptr4 = (int)pci_config_get32(conf_handle, data.off);
1943                         break;
1944                 }
1945 
1946                 break;
1947 
1948         case unm_nic_cmd_pci_config_write:
1949 
1950                 if (adapter->pci_cfg_handle != NULL) {
1951                         conf_handle = adapter->pci_cfg_handle;
1952                 } else if ((retval = pci_config_setup(adapter->dip,
1953                     &conf_handle)) != DDI_SUCCESS) {
1954                         DPRINTF(-1, (CE_WARN, "!%s: pci_config_setup failed"
1955                             " error:%d\n", unm_nic_driver_name, retval));
1956                         goto error_out;
1957                 } else {
1958                         adapter->pci_cfg_handle = conf_handle;
1959                 }
1960 
1961                 switch (data.size) {
1962                 case 1:
1963                         pci_config_put8(conf_handle,
1964                             data.off, *(char *)&(data.uabc));
1965                         break;
1966                 case 2:
1967                         pci_config_put16(conf_handle,
1968                             data.off, *(short *)(uintptr_t)&(data.uabc));
1969                         break;
1970                 case 4:
1971                         pci_config_put32(conf_handle,
1972                             data.off, *(u32 *)(uintptr_t)&(data.uabc));
1973                         break;
1974                 }
1975                 data.size = 0;
1976                 break;
1977 
1978         case unm_nic_cmd_get_stats:
1979                 data.rv = adapter->unm_nic_fill_statistics(adapter,
1980                     (struct unm_statistics *)up_data);
1981                 data.size = sizeof (struct unm_statistics);
1982 
1983                 break;
1984 
1985         case unm_nic_cmd_clear_stats:
1986                 data.rv = adapter->unm_nic_clear_statistics(adapter);
1987                 break;
1988 
1989         case unm_nic_cmd_get_version:
1990                 (void) memcpy(up_data, UNM_NIC_VERSIONID,
1991                     sizeof (UNM_NIC_VERSIONID));
1992                 data.size = sizeof (UNM_NIC_VERSIONID);
1993 
1994                 break;
1995 
1996         case unm_nic_cmd_get_phy_type:
1997                 cmn_err(CE_WARN, "unm_nic_cmd_get_phy_type unimplemented\n");
1998                 break;
1999 
2000         case unm_nic_cmd_efuse_chip_id:
2001                 efuse_chip_id = adapter->unm_nic_pci_read_normalize(adapter,
2002                     UNM_EFUSE_CHIP_ID_HIGH);
2003                 efuse_chip_id <<= 32;
2004                 efuse_chip_id |= adapter->unm_nic_pci_read_normalize(adapter,
2005                     UNM_EFUSE_CHIP_ID_LOW);
2006                 (void) memcpy(up_data, &efuse_chip_id, sizeof (uint64_t));
2007                 data.rv = 0;
2008                 break;
2009 
2010         default:
2011                 cmn_err(CE_WARN, "%s%d: bad command %d\n", adapter->name,
2012                     adapter->instance, data.cmd);
2013                 data.rv = GLD_NOTSUPPORTED;
2014                 data.size = 0;
2015                 goto error_out;
2016         }
2017 
2018 work_done:
2019         miocack(wq, mp, data.size, data.rv);
2020         return (DDI_SUCCESS);
2021 
2022 error_out:
2023         cmn_err(CE_WARN, "%s(%d) ioctl error\n", __FUNCTION__, data.cmd);
2024         miocnak(wq, mp, 0, EINVAL);
2025         return (retval);
2026 }
2027 
2028 /*
2029  * Local datatype for defining tables of (Offset, Name) pairs
2030  */
2031 typedef struct {
2032         offset_t        index;
2033         char            *name;
2034 } unm_ksindex_t;
2035 
2036 static const unm_ksindex_t unm_kstat[] = {
2037         { 0,            "freehdls"              },
2038         { 1,            "freecmds"              },
2039         { 2,            "tx_bcopy_threshold"    },
2040         { 3,            "rx_bcopy_threshold"    },
2041         { 4,            "xmitcalled"            },
2042         { 5,            "xmitedframes"          },
2043         { 6,            "xmitfinished"          },
2044         { 7,            "txbytes"               },
2045         { 8,            "txcopyed"              },
2046         { 9,            "txmapped"              },
2047         { 10,           "outoftxdmahdl"         },
2048         { 11,           "outofcmddesc"          },
2049         { 12,           "txdropped"             },
2050         { 13,           "polled"                },
2051         { 14,           "uphappy"               },
2052         { 15,           "updropped"             },
2053         { 16,           "csummed"               },
2054         { 17,           "no_rcv"                },
2055         { 18,           "rxbytes"               },
2056         { 19,           "rxcopyed"              },
2057         { 20,           "rxmapped"              },
2058         { 21,           "desballocfailed"       },
2059         { 22,           "outofrxbuf"            },
2060         { 23,           "promiscmode"           },
2061         { 24,           "rxbufshort"            },
2062         { 25,           "allocbfailed"          },
2063         { -1,           NULL                    }
2064 };
2065 
2066 static int
2067 unm_kstat_update(kstat_t *ksp, int flag)
2068 {
2069         unm_adapter *adapter;
2070         kstat_named_t *knp;
2071 
2072         if (flag != KSTAT_READ)
2073                 return (EACCES);
2074 
2075         adapter = ksp->ks_private;
2076         knp = ksp->ks_data;
2077 
2078         (knp++)->value.ui32 = adapter->freehdls;
2079         (knp++)->value.ui64 = adapter->freecmds;
2080         (knp++)->value.ui64 = adapter->tx_bcopy_threshold;
2081         (knp++)->value.ui64 = adapter->rx_bcopy_threshold;
2082 
2083         (knp++)->value.ui64 = adapter->stats.xmitcalled;
2084         (knp++)->value.ui64 = adapter->stats.xmitedframes;
2085         (knp++)->value.ui64 = adapter->stats.xmitfinished;
2086         (knp++)->value.ui64 = adapter->stats.txbytes;
2087         (knp++)->value.ui64 = adapter->stats.txcopyed;
2088         (knp++)->value.ui64 = adapter->stats.txmapped;
2089         (knp++)->value.ui64 = adapter->stats.outoftxdmahdl;
2090         (knp++)->value.ui64 = adapter->stats.outofcmddesc;
2091         (knp++)->value.ui64 = adapter->stats.txdropped;
2092         (knp++)->value.ui64 = adapter->stats.polled;
2093         (knp++)->value.ui64 = adapter->stats.uphappy;
2094         (knp++)->value.ui64 = adapter->stats.updropped;
2095         (knp++)->value.ui64 = adapter->stats.csummed;
2096         (knp++)->value.ui64 = adapter->stats.no_rcv;
2097         (knp++)->value.ui64 = adapter->stats.rxbytes;
2098         (knp++)->value.ui64 = adapter->stats.rxcopyed;
2099         (knp++)->value.ui64 = adapter->stats.rxmapped;
2100         (knp++)->value.ui64 = adapter->stats.desballocfailed;
2101         (knp++)->value.ui64 = adapter->stats.outofrxbuf;
2102         (knp++)->value.ui64 = adapter->stats.promiscmode;
2103         (knp++)->value.ui64 = adapter->stats.rxbufshort;
2104         (knp++)->value.ui64 = adapter->stats.allocbfailed;
2105 
2106         return (0);
2107 }
2108 
2109 static kstat_t *
2110 unm_setup_named_kstat(unm_adapter *adapter, int instance, char *name,
2111         const unm_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
2112 {
2113         kstat_t *ksp;
2114         kstat_named_t *knp;
2115         char *np;
2116         int type;
2117         int count = 0;
2118 
2119         size /= sizeof (unm_ksindex_t);
2120         ksp = kstat_create(unm_nic_driver_name, instance, name, "net",
2121             KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
2122         if (ksp == NULL)
2123                 return (NULL);
2124 
2125         ksp->ks_private = adapter;
2126         ksp->ks_update = update;
2127         for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
2128                 count++;
2129                 switch (*np) {
2130                 default:
2131                         type = KSTAT_DATA_UINT64;
2132                         break;
2133                 case '%':
2134                         np += 1;
2135                         type = KSTAT_DATA_UINT32;
2136                         break;
2137                 case '$':
2138                         np += 1;
2139                         type = KSTAT_DATA_STRING;
2140                         break;
2141                 case '&':
2142                         np += 1;
2143                         type = KSTAT_DATA_CHAR;
2144                         break;
2145                 }
2146                 kstat_named_init(knp, np, type);
2147         }
2148         kstat_install(ksp);
2149 
2150         return (ksp);
2151 }
2152 
2153 void
2154 unm_init_kstats(unm_adapter* adapter, int instance)
2155 {
2156         adapter->kstats[0] = unm_setup_named_kstat(adapter,
2157             instance, "kstatinfo", unm_kstat,
2158             sizeof (unm_kstat), unm_kstat_update);
2159 }
2160 
2161 void
2162 unm_fini_kstats(unm_adapter* adapter)
2163 {
2164 
2165         if (adapter->kstats[0] != NULL) {
2166                         kstat_delete(adapter->kstats[0]);
2167                         adapter->kstats[0] = NULL;
2168                 }
2169 }
2170 
2171 static int
2172 unm_nic_set_pauseparam(unm_adapter *adapter, unm_pauseparam_t *pause)
2173 {
2174         int ret = 0;
2175 
2176         if (adapter->ahw.board_type == UNM_NIC_GBE) {
2177                 if (unm_niu_gbe_set_rx_flow_ctl(adapter, pause->rx_pause))
2178                         ret = -EIO;
2179 
2180                 if (unm_niu_gbe_set_tx_flow_ctl(adapter, pause->tx_pause))
2181                         ret = -EIO;
2182 
2183         } else if (adapter->ahw.board_type == UNM_NIC_XGBE) {
2184                 if (unm_niu_xg_set_tx_flow_ctl(adapter, pause->tx_pause))
2185                         ret =  -EIO;
2186         } else
2187                 ret = -EIO;
2188 
2189         return (ret);
2190 }
2191 
2192 /*
2193  * GLD/MAC interfaces
2194  */
2195 static int
2196 ntxn_m_start(void *arg)
2197 {
2198         unm_adapter     *adapter = arg;
2199         int             ring;
2200 
2201         UNM_SPIN_LOCK(&adapter->lock);
2202         if (adapter->is_up == UNM_ADAPTER_UP_MAGIC) {
2203                 UNM_SPIN_UNLOCK(&adapter->lock);
2204                 return (DDI_SUCCESS);
2205         }
2206 
2207         if (create_rxtx_rings(adapter) != DDI_SUCCESS) {
2208                 UNM_SPIN_UNLOCK(&adapter->lock);
2209                 return (DDI_FAILURE);
2210         }
2211 
2212         if (init_firmware(adapter) != DDI_SUCCESS) {
2213                 UNM_SPIN_UNLOCK(&adapter->lock);
2214                 cmn_err(CE_WARN, "%s%d: Failed to init firmware\n",
2215                     adapter->name, adapter->instance);
2216                 goto dest_rings;
2217         }
2218 
2219         unm_nic_clear_stats(adapter);
2220 
2221         if (unm_nic_hw_resources(adapter) != 0) {
2222                 UNM_SPIN_UNLOCK(&adapter->lock);
2223                 cmn_err(CE_WARN, "%s%d: Error setting hw resources\n",
2224                     adapter->name, adapter->instance);
2225                 goto dest_rings;
2226         }
2227 
2228         if (adapter->fw_major < 4) {
2229                 adapter->crb_addr_cmd_producer =
2230                     crb_cmd_producer[adapter->portnum];
2231                 adapter->crb_addr_cmd_consumer =
2232                     crb_cmd_consumer[adapter->portnum];
2233                 unm_nic_update_cmd_producer(adapter, 0);
2234                 unm_nic_update_cmd_consumer(adapter, 0);
2235         }
2236 
2237         for (ring = 0; ring < adapter->max_rds_rings; ring++) {
2238                 if (unm_post_rx_buffers(adapter, ring) != DDI_SUCCESS) {
2239                         UNM_SPIN_UNLOCK(&adapter->lock);
2240                         goto free_hw_res;
2241                 }
2242         }
2243 
2244         if (unm_nic_macaddr_set(adapter, adapter->mac_addr) != 0) {
2245                 UNM_SPIN_UNLOCK(&adapter->lock);
2246                 cmn_err(CE_WARN, "%s%d: Could not set mac address\n",
2247                     adapter->name, adapter->instance);
2248                 goto free_hw_res;
2249         }
2250 
2251         if (unm_nic_init_port(adapter) != 0) {
2252                 UNM_SPIN_UNLOCK(&adapter->lock);
2253                 cmn_err(CE_WARN, "%s%d: Could not initialize port\n",
2254                     adapter->name, adapter->instance);
2255                 goto free_hw_res;
2256         }
2257 
2258         unm_nic_set_link_parameters(adapter);
2259 
2260         /*
2261          * P2 and P3 should be handled similarly.
2262          */
2263         if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
2264                 if (unm_nic_set_promisc_mode(adapter) != 0) {
2265                         UNM_SPIN_UNLOCK(&adapter->lock);
2266                         cmn_err(CE_WARN, "%s%d: Could not set promisc mode\n",
2267                             adapter->name, adapter->instance);
2268                         goto stop_and_free;
2269                 }
2270         } else {
2271                 nx_p3_nic_set_multi(adapter);
2272         }
2273         adapter->stats.promiscmode = 1;
2274 
2275         if (unm_nic_set_mtu(adapter, adapter->mtu) != 0) {
2276                 UNM_SPIN_UNLOCK(&adapter->lock);
2277                 cmn_err(CE_WARN, "%s%d: Could not set mtu\n",
2278                     adapter->name, adapter->instance);
2279                 goto stop_and_free;
2280         }
2281 
2282         adapter->watchdog_timer = timeout((void (*)(void *))&unm_watchdog,
2283             (void *)adapter, 0);
2284 
2285         adapter->is_up = UNM_ADAPTER_UP_MAGIC;
2286 
2287         if (adapter->intr_type == DDI_INTR_TYPE_MSI)
2288                 (void) ddi_intr_block_enable(&adapter->intr_handle, 1);
2289         else
2290                 (void) ddi_intr_enable(adapter->intr_handle);
2291         unm_nic_enable_int(adapter);
2292 
2293         UNM_SPIN_UNLOCK(&adapter->lock);
2294         return (GLD_SUCCESS);
2295 
2296 stop_and_free:
2297         unm_nic_stop_port(adapter);
2298 free_hw_res:
2299         unm_free_hw_resources(adapter);
2300 dest_rings:
2301         destroy_rxtx_rings(adapter);
2302         return (DDI_FAILURE);
2303 }
2304 
2305 
2306 /*
2307  * This code is kept here for reference so as to
2308  * see if something different is required to be done
2309  * in GLDV3. This will be deleted later.
2310  */
2311 /* ARGSUSED */
2312 static void
2313 ntxn_m_stop(void *arg)
2314 {
2315 }
2316 
2317 /*ARGSUSED*/
2318 static int
2319 ntxn_m_multicst(void *arg, boolean_t add, const uint8_t *ep)
2320 {
2321         /*
2322          * When we correctly implement this, invoke nx_p3_nic_set_multi()
2323          * or nx_p2_nic_set_multi() here.
2324          */
2325         return (GLD_SUCCESS);
2326 }
2327 
2328 /*ARGSUSED*/
2329 static int
2330 ntxn_m_promisc(void *arg, boolean_t on)
2331 {
2332 #if 0
2333         int err = 0;
2334         struct unm_adapter_s *adapter = arg;
2335 
2336         err = on ? unm_nic_set_promisc_mode(adapter) :
2337             unm_nic_unset_promisc_mode(adapter);
2338 
2339         if (err)
2340                 return (GLD_FAILURE);
2341 #endif
2342 
2343         return (GLD_SUCCESS);
2344 }
2345 
2346 static int
2347 ntxn_m_stat(void *arg, uint_t stat, uint64_t *val)
2348 {
2349         struct unm_adapter_s            *adapter = arg;
2350         struct unm_adapter_stats        *portstat = &adapter->stats;
2351 
2352         switch (stat) {
2353         case MAC_STAT_IFSPEED:
2354                 if (adapter->ahw.board_type == UNM_NIC_XGBE) {
2355                         /* 10 Gigs */
2356                         *val = 10000000000ULL;
2357                 } else {
2358                         /* 1 Gig */
2359                         *val = 1000000000;
2360                 }
2361                 break;
2362 
2363         case MAC_STAT_MULTIRCV:
2364                 *val = 0;
2365                 break;
2366 
2367         case MAC_STAT_BRDCSTRCV:
2368         case MAC_STAT_BRDCSTXMT:
2369                 *val = 0;
2370                 break;
2371 
2372         case MAC_STAT_NORCVBUF:
2373                 *val = portstat->updropped;
2374                 break;
2375 
2376         case MAC_STAT_NOXMTBUF:
2377                 *val = portstat->txdropped;
2378                 break;
2379 
2380         case MAC_STAT_RBYTES:
2381                 *val = portstat->rxbytes;
2382                 break;
2383 
2384         case MAC_STAT_OBYTES:
2385                 *val = portstat->txbytes;
2386                 break;
2387 
2388         case MAC_STAT_OPACKETS:
2389                 *val = portstat->xmitedframes;
2390                 break;
2391 
2392         case MAC_STAT_IPACKETS:
2393                 *val = portstat->uphappy;
2394                 break;
2395 
2396         case MAC_STAT_OERRORS:
2397                 *val = portstat->xmitcalled - portstat->xmitedframes;
2398                 break;
2399 
2400         case ETHER_STAT_LINK_DUPLEX:
2401                 *val = LINK_DUPLEX_FULL;
2402                 break;
2403 
2404         default:
2405                 /*
2406                  * Shouldn't reach here...
2407                  */
2408                 *val = 0;
2409                 DPRINTF(0, (CE_WARN, ": unrecognized parameter = %d, value "
2410                     "returned 1\n", stat));
2411 
2412         }
2413 
2414         return (0);
2415 }
2416 
2417 static int
2418 ntxn_m_unicst(void *arg, const uint8_t *mac)
2419 {
2420         struct unm_adapter_s *adapter = arg;
2421 
2422         DPRINTF(-1, (CE_CONT, "%s: called\n", __func__));
2423 
2424         if (unm_nic_macaddr_set(adapter, (uint8_t *)mac))
2425                 return (EAGAIN);
2426         bcopy(mac, adapter->mac_addr, ETHERADDRL);
2427 
2428         return (0);
2429 }
2430 
2431 static mblk_t *
2432 ntxn_m_tx(void *arg, mblk_t *mp)
2433 {
2434         unm_adapter *adapter = arg;
2435         mblk_t *next;
2436 
2437         while (mp != NULL) {
2438                 next = mp->b_next;
2439                 mp->b_next = NULL;
2440 
2441                 if (unm_nic_xmit_frame(adapter, mp) != B_TRUE) {
2442                         mp->b_next = next;
2443                         break;
2444                 }
2445                 mp = next;
2446                 adapter->stats.xmitedframes++;
2447         }
2448 
2449         return (mp);
2450 }
2451 
2452 static void
2453 ntxn_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
2454 {
2455         int             cmd;
2456         struct iocblk   *iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
2457         struct unm_adapter_s *adapter = (struct unm_adapter_s *)arg;
2458         enum ioc_reply status = IOC_DONE;
2459 
2460         iocp->ioc_error = 0;
2461         cmd = iocp->ioc_cmd;
2462 
2463         if (cmd == ND_GET || cmd == ND_SET) {
2464                 status = unm_nd_ioctl(adapter, wq, mp, iocp);
2465                 switch (status) {
2466                 default:
2467                 case IOC_INVAL:
2468                         miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
2469                             EINVAL : iocp->ioc_error);
2470                         break;
2471 
2472                 case IOC_DONE:
2473                         break;
2474 
2475                 case IOC_RESTART_ACK:
2476                 case IOC_ACK:
2477                         miocack(wq, mp, 0, 0);
2478                         break;
2479 
2480                 case IOC_RESTART_REPLY:
2481                 case IOC_REPLY:
2482                         mp->b_datap->db_type = iocp->ioc_error == 0 ?
2483                             M_IOCACK : M_IOCNAK;
2484                         qreply(wq, mp);
2485                         break;
2486                 }
2487         } else if (cmd <= UNM_NIC_NAME && cmd >= UNM_CMD_START) {
2488                 unm_nic_ioctl(adapter, cmd, wq, mp);
2489                 return;
2490         } else {
2491                 miocnak(wq, mp, 0, EINVAL);
2492                 return;
2493         }
2494 }
2495 
2496 /* ARGSUSED */
2497 static boolean_t
2498 ntxn_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
2499 {
2500         switch (cap) {
2501         case MAC_CAPAB_HCKSUM:
2502                 {
2503                         uint32_t *txflags = cap_data;
2504 
2505                         *txflags = (HCKSUM_ENABLE |
2506                             HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM);
2507                 }
2508                 break;
2509 
2510 #ifdef SOLARIS11
2511         case MAC_CAPAB_ANCHOR_VNIC:
2512         case MAC_CAPAB_MULTIFACTADDR:
2513 #else
2514         case MAC_CAPAB_POLL:
2515         case MAC_CAPAB_MULTIADDRESS:
2516 #endif
2517         default:
2518                 return (B_FALSE);
2519         }
2520 
2521         return (B_TRUE);
2522 }
2523 
2524 #define NETXEN_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB)
2525 
2526 static mac_callbacks_t ntxn_m_callbacks = {
2527         NETXEN_M_CALLBACK_FLAGS,
2528         ntxn_m_stat,
2529         ntxn_m_start,
2530         ntxn_m_stop,
2531         ntxn_m_promisc,
2532         ntxn_m_multicst,
2533         ntxn_m_unicst,
2534         ntxn_m_tx,
2535         NULL,                   /* mc_reserved */
2536         ntxn_m_ioctl,
2537         ntxn_m_getcapab,
2538         NULL,                   /* mc_open */
2539         NULL,                   /* mc_close */
2540         NULL,                   /* mc_setprop */
2541         NULL                    /* mc_getprop */
2542 };
2543 
2544 int
2545 unm_register_mac(unm_adapter *adapter)
2546 {
2547         int ret;
2548         mac_register_t *macp;
2549         unm_pauseparam_t pause;
2550 
2551         dev_info_t *dip = adapter->dip;
2552 
2553         if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
2554                 cmn_err(CE_WARN, "Memory not available\n");
2555                 return (DDI_FAILURE);
2556         }
2557 
2558         macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
2559         macp->m_driver = adapter;
2560         macp->m_dip = dip;
2561         macp->m_instance = adapter->instance;
2562         macp->m_src_addr = adapter->mac_addr;
2563         macp->m_callbacks = &ntxn_m_callbacks;
2564         macp->m_min_sdu = 0;
2565         macp->m_max_sdu = adapter->mtu;
2566 #ifdef SOLARIS11
2567         macp->m_margin = VLAN_TAGSZ;
2568 #endif /* SOLARIS11 */
2569 
2570         ret = mac_register(macp, &adapter->mach);
2571         mac_free(macp);
2572         if (ret != 0) {
2573                 cmn_err(CE_WARN, "mac_register failed for port %d\n",
2574                     adapter->portnum);
2575                 return (DDI_FAILURE);
2576         }
2577 
2578         unm_init_kstats(adapter, adapter->instance);
2579 
2580         /* Register NDD-tweakable parameters */
2581         if (unm_nd_init(adapter)) {
2582                 cmn_err(CE_WARN, "unm_nd_init() failed");
2583                 return (DDI_FAILURE);
2584         }
2585 
2586         pause.rx_pause = adapter->nd_params[PARAM_ADV_PAUSE_CAP].ndp_val;
2587         pause.tx_pause = adapter->nd_params[PARAM_ADV_ASYM_PAUSE_CAP].ndp_val;
2588 
2589         if (unm_nic_set_pauseparam(adapter, &pause)) {
2590                 cmn_err(CE_WARN, "\nBad Pause settings RX %d, Tx %d",
2591                     pause.rx_pause, pause.tx_pause);
2592         }
2593         adapter->nd_params[PARAM_PAUSE_CAP].ndp_val = pause.rx_pause;
2594         adapter->nd_params[PARAM_ASYM_PAUSE_CAP].ndp_val = pause.tx_pause;
2595 
2596         return (DDI_SUCCESS);
2597 }