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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 /*
  26  * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver.
  27  */
  28 #include        <sys/nxge/nxge_impl.h>
  29 #include        <sys/nxge/nxge_hio.h>
  30 #include        <sys/nxge/nxge_rxdma.h>
  31 #include        <sys/pcie.h>
  32 
  33 uint32_t        nxge_use_partition = 0;         /* debug partition flag */
  34 uint32_t        nxge_dma_obp_props_only = 1;    /* use obp published props */
  35 uint32_t        nxge_use_rdc_intr = 1;          /* debug to assign rdc intr */
  36 /*
  37  * PSARC/2007/453 MSI-X interrupt limit override
  38  */
  39 uint32_t        nxge_msi_enable = 2;
  40 
  41 /*
  42  * Software workaround for a Neptune (PCI-E)
  43  * hardware interrupt bug which the hardware
  44  * may generate spurious interrupts after the
  45  * device interrupt handler was removed. If this flag
  46  * is enabled, the driver will reset the
  47  * hardware when devices are being detached.
  48  */
  49 uint32_t        nxge_peu_reset_enable = 0;
  50 
  51 /*
  52  * Software workaround for the hardware
  53  * checksum bugs that affect packet transmission
  54  * and receive:
  55  *
  56  * Usage of nxge_cksum_offload:
  57  *
  58  *  (1) nxge_cksum_offload = 0 (default):
  59  *      - transmits packets:
  60  *        TCP: uses the hardware checksum feature.
  61  *        UDP: driver will compute the software checksum
  62  *             based on the partial checksum computed
  63  *             by the IP layer.
  64  *      - receives packets
  65  *        TCP: marks packets checksum flags based on hardware result.
  66  *        UDP: will not mark checksum flags.
  67  *
  68  *  (2) nxge_cksum_offload = 1:
  69  *      - transmit packets:
  70  *        TCP/UDP: uses the hardware checksum feature.
  71  *      - receives packets
  72  *        TCP/UDP: marks packet checksum flags based on hardware result.
  73  *
  74  *  (3) nxge_cksum_offload = 2:
  75  *      - The driver will not register its checksum capability.
  76  *        Checksum for both TCP and UDP will be computed
  77  *        by the stack.
  78  *      - The software LSO is not allowed in this case.
  79  *
  80  *  (4) nxge_cksum_offload > 2:
  81  *      - Will be treated as it is set to 2
  82  *        (stack will compute the checksum).
  83  *
  84  *  (5) If the hardware bug is fixed, this workaround
  85  *      needs to be updated accordingly to reflect
  86  *      the new hardware revision.
  87  */
  88 uint32_t        nxge_cksum_offload = 0;
  89 
  90 /*
  91  * Globals: tunable parameters (/etc/system or adb)
  92  *
  93  */
  94 uint32_t        nxge_rbr_size = NXGE_RBR_RBB_DEFAULT;
  95 uint32_t        nxge_rbr_spare_size = 0;
  96 uint32_t        nxge_rcr_size = NXGE_RCR_DEFAULT;
  97 uint16_t        nxge_rdc_buf_offset = SW_OFFSET_NO_OFFSET;
  98 uint32_t        nxge_tx_ring_size = NXGE_TX_RING_DEFAULT;
  99 boolean_t       nxge_no_msg = B_TRUE;           /* control message display */
 100 uint32_t        nxge_no_link_notify = 0;        /* control DL_NOTIFY */
 101 uint32_t        nxge_bcopy_thresh = TX_BCOPY_MAX;
 102 uint32_t        nxge_dvma_thresh = TX_FASTDVMA_MIN;
 103 uint32_t        nxge_dma_stream_thresh = TX_STREAM_MIN;
 104 uint32_t        nxge_jumbo_mtu  = TX_JUMBO_MTU;
 105 nxge_tx_mode_t  nxge_tx_scheme = NXGE_USE_SERIAL;
 106 
 107 /* MAX LSO size */
 108 #define         NXGE_LSO_MAXLEN 65535
 109 uint32_t        nxge_lso_max = NXGE_LSO_MAXLEN;
 110 
 111 
 112 /*
 113  * Add tunable to reduce the amount of time spent in the
 114  * ISR doing Rx Processing.
 115  */
 116 uint32_t nxge_max_rx_pkts = 1024;
 117 
 118 /*
 119  * Tunables to manage the receive buffer blocks.
 120  *
 121  * nxge_rx_threshold_hi: copy all buffers.
 122  * nxge_rx_bcopy_size_type: receive buffer block size type.
 123  * nxge_rx_threshold_lo: copy only up to tunable block size type.
 124  */
 125 nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6;
 126 nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
 127 nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3;
 128 
 129 /* Use kmem_alloc() to allocate data buffers. */
 130 #if defined(__sparc)
 131 uint32_t        nxge_use_kmem_alloc = 1;
 132 #elif defined(__i386)
 133 uint32_t        nxge_use_kmem_alloc = 0;
 134 #else
 135 uint32_t        nxge_use_kmem_alloc = 1;
 136 #endif
 137 
 138 rtrace_t npi_rtracebuf;
 139 
 140 /*
 141  * The hardware sometimes fails to allow enough time for the link partner
 142  * to send an acknowledgement for packets that the hardware sent to it. The
 143  * hardware resends the packets earlier than it should be in those instances.
 144  * This behavior caused some switches to acknowledge the wrong packets
 145  * and it triggered the fatal error.
 146  * This software workaround is to set the replay timer to a value
 147  * suggested by the hardware team.
 148  *
 149  * PCI config space replay timer register:
 150  *     The following replay timeout value is 0xc
 151  *     for bit 14:18.
 152  */
 153 #define PCI_REPLAY_TIMEOUT_CFG_OFFSET   0xb8
 154 #define PCI_REPLAY_TIMEOUT_SHIFT        14
 155 
 156 uint32_t        nxge_set_replay_timer = 1;
 157 uint32_t        nxge_replay_timeout = 0xc;
 158 
 159 /*
 160  * The transmit serialization sometimes causes
 161  * longer sleep before calling the driver transmit
 162  * function as it sleeps longer than it should.
 163  * The performace group suggests that a time wait tunable
 164  * can be used to set the maximum wait time when needed
 165  * and the default is set to 1 tick.
 166  */
 167 uint32_t        nxge_tx_serial_maxsleep = 1;
 168 
 169 #if     defined(sun4v)
 170 /*
 171  * Hypervisor N2/NIU services information.
 172  */
 173 /*
 174  * The following is the default API supported:
 175  * major 1 and minor 1.
 176  *
 177  * Please update the MAX_NIU_MAJORS,
 178  * MAX_NIU_MINORS, and minor number supported
 179  * when the newer Hypervior API interfaces
 180  * are added. Also, please update nxge_hsvc_register()
 181  * if needed.
 182  */
 183 static hsvc_info_t niu_hsvc = {
 184         HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER,
 185         NIU_MINOR_VER, "nxge"
 186 };
 187 
 188 static int nxge_hsvc_register(p_nxge_t);
 189 #endif
 190 
 191 /*
 192  * Function Prototypes
 193  */
 194 static int nxge_attach(dev_info_t *, ddi_attach_cmd_t);
 195 static int nxge_detach(dev_info_t *, ddi_detach_cmd_t);
 196 static void nxge_unattach(p_nxge_t);
 197 static int nxge_quiesce(dev_info_t *);
 198 
 199 #if NXGE_PROPERTY
 200 static void nxge_remove_hard_properties(p_nxge_t);
 201 #endif
 202 
 203 /*
 204  * These two functions are required by nxge_hio.c
 205  */
 206 extern int nxge_m_mmac_remove(void *arg, int slot);
 207 extern void nxge_grp_cleanup(p_nxge_t nxge);
 208 
 209 static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t);
 210 
 211 static nxge_status_t nxge_setup_mutexes(p_nxge_t);
 212 static void nxge_destroy_mutexes(p_nxge_t);
 213 
 214 static nxge_status_t nxge_map_regs(p_nxge_t nxgep);
 215 static void nxge_unmap_regs(p_nxge_t nxgep);
 216 #ifdef  NXGE_DEBUG
 217 static void nxge_test_map_regs(p_nxge_t nxgep);
 218 #endif
 219 
 220 static nxge_status_t nxge_add_intrs(p_nxge_t nxgep);
 221 static void nxge_remove_intrs(p_nxge_t nxgep);
 222 
 223 static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep);
 224 static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t);
 225 static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t);
 226 static void nxge_intrs_enable(p_nxge_t nxgep);
 227 static void nxge_intrs_disable(p_nxge_t nxgep);
 228 
 229 static void nxge_suspend(p_nxge_t);
 230 static nxge_status_t nxge_resume(p_nxge_t);
 231 
 232 static nxge_status_t nxge_setup_dev(p_nxge_t);
 233 static void nxge_destroy_dev(p_nxge_t);
 234 
 235 static nxge_status_t nxge_alloc_mem_pool(p_nxge_t);
 236 static void nxge_free_mem_pool(p_nxge_t);
 237 
 238 nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t);
 239 static void nxge_free_rx_mem_pool(p_nxge_t);
 240 
 241 nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t);
 242 static void nxge_free_tx_mem_pool(p_nxge_t);
 243 
 244 static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t,
 245         struct ddi_dma_attr *,
 246         size_t, ddi_device_acc_attr_t *, uint_t,
 247         p_nxge_dma_common_t);
 248 
 249 static void nxge_dma_mem_free(p_nxge_dma_common_t);
 250 static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t);
 251 
 252 static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t,
 253         p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
 254 static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
 255 
 256 static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t,
 257         p_nxge_dma_common_t *, size_t);
 258 static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
 259 
 260 extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t,
 261         p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
 262 static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
 263 
 264 extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t,
 265         p_nxge_dma_common_t *,
 266         size_t);
 267 static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
 268 
 269 static int nxge_init_common_dev(p_nxge_t);
 270 static void nxge_uninit_common_dev(p_nxge_t);
 271 extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *,
 272     char *, caddr_t);
 273 #if defined(sun4v)
 274 extern nxge_status_t nxge_hio_rdc_enable(p_nxge_t nxgep);
 275 extern nxge_status_t nxge_hio_rdc_intr_arm(p_nxge_t nxge, boolean_t arm);
 276 #endif
 277 
 278 /*
 279  * The next declarations are for the GLDv3 interface.
 280  */
 281 static int nxge_m_start(void *);
 282 static void nxge_m_stop(void *);
 283 static int nxge_m_multicst(void *, boolean_t, const uint8_t *);
 284 static int nxge_m_promisc(void *, boolean_t);
 285 static void nxge_m_ioctl(void *, queue_t *, mblk_t *);
 286 nxge_status_t nxge_mac_register(p_nxge_t);
 287 static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr,
 288         int slot, int rdctbl, boolean_t usetbl);
 289 void nxge_mmac_kstat_update(p_nxge_t nxgep, int slot,
 290         boolean_t factory);
 291 
 292 static void nxge_m_getfactaddr(void *, uint_t, uint8_t *);
 293 static  boolean_t nxge_m_getcapab(void *, mac_capab_t, void *);
 294 static int nxge_m_setprop(void *, const char *, mac_prop_id_t,
 295     uint_t, const void *);
 296 static int nxge_m_getprop(void *, const char *, mac_prop_id_t,
 297     uint_t, void *);
 298 static void nxge_m_propinfo(void *, const char *, mac_prop_id_t,
 299     mac_prop_info_handle_t);
 300 static void nxge_priv_propinfo(const char *, mac_prop_info_handle_t);
 301 static int nxge_set_priv_prop(nxge_t *, const char *, uint_t,
 302     const void *);
 303 static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, void *);
 304 static void nxge_fill_ring(void *, mac_ring_type_t, const int, const int,
 305     mac_ring_info_t *, mac_ring_handle_t);
 306 static void nxge_group_add_ring(mac_group_driver_t, mac_ring_driver_t,
 307     mac_ring_type_t);
 308 static void nxge_group_rem_ring(mac_group_driver_t, mac_ring_driver_t,
 309     mac_ring_type_t);
 310 
 311 static void nxge_niu_peu_reset(p_nxge_t nxgep);
 312 static void nxge_set_pci_replay_timeout(nxge_t *);
 313 
 314 char *nxge_priv_props[] = {
 315         "_adv_10gfdx_cap",
 316         "_adv_pause_cap",
 317         "_function_number",
 318         "_fw_version",
 319         "_port_mode",
 320         "_hot_swap_phy",
 321         "_rxdma_intr_time",
 322         "_rxdma_intr_pkts",
 323         "_class_opt_ipv4_tcp",
 324         "_class_opt_ipv4_udp",
 325         "_class_opt_ipv4_ah",
 326         "_class_opt_ipv4_sctp",
 327         "_class_opt_ipv6_tcp",
 328         "_class_opt_ipv6_udp",
 329         "_class_opt_ipv6_ah",
 330         "_class_opt_ipv6_sctp",
 331         "_soft_lso_enable",
 332         NULL
 333 };
 334 
 335 #define NXGE_NEPTUNE_MAGIC      0x4E584745UL
 336 #define MAX_DUMP_SZ 256
 337 
 338 #define NXGE_M_CALLBACK_FLAGS   \
 339         (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
 340 
 341 mac_callbacks_t nxge_m_callbacks = {
 342         NXGE_M_CALLBACK_FLAGS,
 343         nxge_m_stat,
 344         nxge_m_start,
 345         nxge_m_stop,
 346         nxge_m_promisc,
 347         nxge_m_multicst,
 348         NULL,
 349         NULL,
 350         NULL,
 351         nxge_m_ioctl,
 352         nxge_m_getcapab,
 353         NULL,
 354         NULL,
 355         nxge_m_setprop,
 356         nxge_m_getprop,
 357         nxge_m_propinfo
 358 };
 359 
 360 void
 361 nxge_err_inject(p_nxge_t, queue_t *, mblk_t *);
 362 
 363 /* PSARC/2007/453 MSI-X interrupt limit override. */
 364 #define NXGE_MSIX_REQUEST_10G   8
 365 #define NXGE_MSIX_REQUEST_1G    2
 366 static int nxge_create_msi_property(p_nxge_t);
 367 /*
 368  * For applications that care about the
 369  * latency, it was requested by PAE and the
 370  * customers that the driver has tunables that
 371  * allow the user to tune it to a higher number
 372  * interrupts to spread the interrupts among
 373  * multiple channels. The DDI framework limits
 374  * the maximum number of MSI-X resources to allocate
 375  * to 8 (ddi_msix_alloc_limit). If more than 8
 376  * is set, ddi_msix_alloc_limit must be set accordingly.
 377  * The default number of MSI interrupts are set to
 378  * 8 for 10G and 2 for 1G link.
 379  */
 380 #define NXGE_MSIX_MAX_ALLOWED   32
 381 uint32_t nxge_msix_10g_intrs = NXGE_MSIX_REQUEST_10G;
 382 uint32_t nxge_msix_1g_intrs = NXGE_MSIX_REQUEST_1G;
 383 
 384 /*
 385  * These global variables control the message
 386  * output.
 387  */
 388 out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG;
 389 uint64_t nxge_debug_level;
 390 
 391 /*
 392  * This list contains the instance structures for the Neptune
 393  * devices present in the system. The lock exists to guarantee
 394  * mutually exclusive access to the list.
 395  */
 396 void                    *nxge_list = NULL;
 397 void                    *nxge_hw_list = NULL;
 398 nxge_os_mutex_t         nxge_common_lock;
 399 nxge_os_mutex_t         nxgedebuglock;
 400 
 401 extern uint64_t         npi_debug_level;
 402 
 403 extern nxge_status_t    nxge_ldgv_init(p_nxge_t, int *, int *);
 404 extern nxge_status_t    nxge_ldgv_init_n2(p_nxge_t, int *, int *);
 405 extern nxge_status_t    nxge_ldgv_uninit(p_nxge_t);
 406 extern nxge_status_t    nxge_intr_ldgv_init(p_nxge_t);
 407 extern void             nxge_fm_init(p_nxge_t,
 408                                         ddi_device_acc_attr_t *,
 409                                         ddi_dma_attr_t *);
 410 extern void             nxge_fm_fini(p_nxge_t);
 411 extern npi_status_t     npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t);
 412 
 413 /*
 414  * Count used to maintain the number of buffers being used
 415  * by Neptune instances and loaned up to the upper layers.
 416  */
 417 uint32_t nxge_mblks_pending = 0;
 418 
 419 /*
 420  * Device register access attributes for PIO.
 421  */
 422 static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = {
 423         DDI_DEVICE_ATTR_V1,
 424         DDI_STRUCTURE_LE_ACC,
 425         DDI_STRICTORDER_ACC,
 426         DDI_DEFAULT_ACC
 427 };
 428 
 429 /*
 430  * Device descriptor access attributes for DMA.
 431  */
 432 static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = {
 433         DDI_DEVICE_ATTR_V0,
 434         DDI_STRUCTURE_LE_ACC,
 435         DDI_STRICTORDER_ACC
 436 };
 437 
 438 /*
 439  * Device buffer access attributes for DMA.
 440  */
 441 static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = {
 442         DDI_DEVICE_ATTR_V0,
 443         DDI_STRUCTURE_BE_ACC,
 444         DDI_STRICTORDER_ACC
 445 };
 446 
 447 ddi_dma_attr_t nxge_desc_dma_attr = {
 448         DMA_ATTR_V0,            /* version number. */
 449         0,                      /* low address */
 450         0xffffffffffffffff,     /* high address */
 451         0xffffffffffffffff,     /* address counter max */
 452 #ifndef NIU_PA_WORKAROUND
 453         0x100000,               /* alignment */
 454 #else
 455         0x2000,
 456 #endif
 457         0xfc00fc,               /* dlim_burstsizes */
 458         0x1,                    /* minimum transfer size */
 459         0xffffffffffffffff,     /* maximum transfer size */
 460         0xffffffffffffffff,     /* maximum segment size */
 461         1,                      /* scatter/gather list length */
 462         (unsigned int) 1,       /* granularity */
 463         0                       /* attribute flags */
 464 };
 465 
 466 ddi_dma_attr_t nxge_tx_dma_attr = {
 467         DMA_ATTR_V0,            /* version number. */
 468         0,                      /* low address */
 469         0xffffffffffffffff,     /* high address */
 470         0xffffffffffffffff,     /* address counter max */
 471 #if defined(_BIG_ENDIAN)
 472         0x2000,                 /* alignment */
 473 #else
 474         0x1000,                 /* alignment */
 475 #endif
 476         0xfc00fc,               /* dlim_burstsizes */
 477         0x1,                    /* minimum transfer size */
 478         0xffffffffffffffff,     /* maximum transfer size */
 479         0xffffffffffffffff,     /* maximum segment size */
 480         5,                      /* scatter/gather list length */
 481         (unsigned int) 1,       /* granularity */
 482         0                       /* attribute flags */
 483 };
 484 
 485 ddi_dma_attr_t nxge_rx_dma_attr = {
 486         DMA_ATTR_V0,            /* version number. */
 487         0,                      /* low address */
 488         0xffffffffffffffff,     /* high address */
 489         0xffffffffffffffff,     /* address counter max */
 490         0x2000,                 /* alignment */
 491         0xfc00fc,               /* dlim_burstsizes */
 492         0x1,                    /* minimum transfer size */
 493         0xffffffffffffffff,     /* maximum transfer size */
 494         0xffffffffffffffff,     /* maximum segment size */
 495         1,                      /* scatter/gather list length */
 496         (unsigned int) 1,       /* granularity */
 497         DDI_DMA_RELAXED_ORDERING /* attribute flags */
 498 };
 499 
 500 ddi_dma_lim_t nxge_dma_limits = {
 501         (uint_t)0,              /* dlim_addr_lo */
 502         (uint_t)0xffffffff,     /* dlim_addr_hi */
 503         (uint_t)0xffffffff,     /* dlim_cntr_max */
 504         (uint_t)0xfc00fc,       /* dlim_burstsizes for 32 and 64 bit xfers */
 505         0x1,                    /* dlim_minxfer */
 506         1024                    /* dlim_speed */
 507 };
 508 
 509 dma_method_t nxge_force_dma = DVMA;
 510 
 511 /*
 512  * dma chunk sizes.
 513  *
 514  * Try to allocate the largest possible size
 515  * so that fewer number of dma chunks would be managed
 516  */
 517 #ifdef NIU_PA_WORKAROUND
 518 size_t alloc_sizes [] = {0x2000};
 519 #else
 520 size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000,
 521                 0x10000, 0x20000, 0x40000, 0x80000,
 522                 0x100000, 0x200000, 0x400000, 0x800000,
 523                 0x1000000, 0x2000000, 0x4000000};
 524 #endif
 525 
 526 /*
 527  * Translate "dev_t" to a pointer to the associated "dev_info_t".
 528  */
 529 
 530 extern void nxge_get_environs(nxge_t *);
 531 
 532 static int
 533 nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 534 {
 535         p_nxge_t        nxgep = NULL;
 536         int             instance;
 537         int             status = DDI_SUCCESS;
 538         uint8_t         portn;
 539         nxge_mmac_t     *mmac_info;
 540 
 541         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach"));
 542 
 543         /*
 544          * Get the device instance since we'll need to setup
 545          * or retrieve a soft state for this instance.
 546          */
 547         instance = ddi_get_instance(dip);
 548 
 549         switch (cmd) {
 550         case DDI_ATTACH:
 551                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH"));
 552                 break;
 553 
 554         case DDI_RESUME:
 555                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME"));
 556                 nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
 557                 if (nxgep == NULL) {
 558                         status = DDI_FAILURE;
 559                         break;
 560                 }
 561                 if (nxgep->dip != dip) {
 562                         status = DDI_FAILURE;
 563                         break;
 564                 }
 565                 if (nxgep->suspended == DDI_PM_SUSPEND) {
 566                         status = ddi_dev_is_needed(nxgep->dip, 0, 1);
 567                 } else {
 568                         status = nxge_resume(nxgep);
 569                 }
 570                 goto nxge_attach_exit;
 571 
 572         case DDI_PM_RESUME:
 573                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME"));
 574                 nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
 575                 if (nxgep == NULL) {
 576                         status = DDI_FAILURE;
 577                         break;
 578                 }
 579                 if (nxgep->dip != dip) {
 580                         status = DDI_FAILURE;
 581                         break;
 582                 }
 583                 status = nxge_resume(nxgep);
 584                 goto nxge_attach_exit;
 585 
 586         default:
 587                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown"));
 588                 status = DDI_FAILURE;
 589                 goto nxge_attach_exit;
 590         }
 591 
 592 
 593         if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) {
 594                 status = DDI_FAILURE;
 595                 goto nxge_attach_exit;
 596         }
 597 
 598         nxgep = ddi_get_soft_state(nxge_list, instance);
 599         if (nxgep == NULL) {
 600                 status = NXGE_ERROR;
 601                 goto nxge_attach_fail2;
 602         }
 603 
 604         nxgep->nxge_magic = NXGE_MAGIC;
 605 
 606         nxgep->drv_state = 0;
 607         nxgep->dip = dip;
 608         nxgep->instance = instance;
 609         nxgep->p_dip = ddi_get_parent(dip);
 610         nxgep->nxge_debug_level = nxge_debug_level;
 611         npi_debug_level = nxge_debug_level;
 612 
 613         /* Are we a guest running in a Hybrid I/O environment? */
 614         nxge_get_environs(nxgep);
 615 
 616         status = nxge_map_regs(nxgep);
 617 
 618         if (status != NXGE_OK) {
 619                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed"));
 620                 goto nxge_attach_fail3;
 621         }
 622 
 623         nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_rx_dma_attr);
 624 
 625         /* Create & initialize the per-Neptune data structure */
 626         /* (even if we're a guest). */
 627         status = nxge_init_common_dev(nxgep);
 628         if (status != NXGE_OK) {
 629                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 630                     "nxge_init_common_dev failed"));
 631                 goto nxge_attach_fail4;
 632         }
 633 
 634         /*
 635          * Software workaround: set the replay timer.
 636          */
 637         if (nxgep->niu_type != N2_NIU) {
 638                 nxge_set_pci_replay_timeout(nxgep);
 639         }
 640 
 641 #if defined(sun4v)
 642         /* This is required by nxge_hio_init(), which follows. */
 643         if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS)
 644                 goto nxge_attach_fail4;
 645 #endif
 646 
 647         if ((status = nxge_hio_init(nxgep)) != NXGE_OK) {
 648                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 649                     "nxge_hio_init failed"));
 650                 goto nxge_attach_fail4;
 651         }
 652 
 653         if (nxgep->niu_type == NEPTUNE_2_10GF) {
 654                 if (nxgep->function_num > 1) {
 655                         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported"
 656                             " function %d. Only functions 0 and 1 are "
 657                             "supported for this card.", nxgep->function_num));
 658                         status = NXGE_ERROR;
 659                         goto nxge_attach_fail4;
 660                 }
 661         }
 662 
 663         if (isLDOMguest(nxgep)) {
 664                 /*
 665                  * Use the function number here.
 666                  */
 667                 nxgep->mac.portnum = nxgep->function_num;
 668                 nxgep->mac.porttype = PORT_TYPE_LOGICAL;
 669 
 670                 /* XXX We'll set the MAC address counts to 1 for now. */
 671                 mmac_info = &nxgep->nxge_mmac_info;
 672                 mmac_info->num_mmac = 1;
 673                 mmac_info->naddrfree = 1;
 674         } else {
 675                 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
 676                 nxgep->mac.portnum = portn;
 677                 if ((portn == 0) || (portn == 1))
 678                         nxgep->mac.porttype = PORT_TYPE_XMAC;
 679                 else
 680                         nxgep->mac.porttype = PORT_TYPE_BMAC;
 681                 /*
 682                  * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC)
 683                  * internally, the rest 2 ports use BMAC (1G "Big" MAC).
 684                  * The two types of MACs have different characterizations.
 685                  */
 686                 mmac_info = &nxgep->nxge_mmac_info;
 687                 if (nxgep->function_num < 2) {
 688                         mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY;
 689                         mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY;
 690                 } else {
 691                         mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY;
 692                         mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY;
 693                 }
 694         }
 695         /*
 696          * Setup the Ndd parameters for the this instance.
 697          */
 698         nxge_init_param(nxgep);
 699 
 700         /*
 701          * Setup Register Tracing Buffer.
 702          */
 703         npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf);
 704 
 705         /* init stats ptr */
 706         nxge_init_statsp(nxgep);
 707 
 708         /*
 709          * Copy the vpd info from eeprom to a local data
 710          * structure, and then check its validity.
 711          */
 712         if (!isLDOMguest(nxgep)) {
 713                 int *regp;
 714                 uint_t reglen;
 715                 int rv;
 716 
 717                 nxge_vpd_info_get(nxgep);
 718 
 719                 /* Find the NIU config handle. */
 720                 rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
 721                     ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS,
 722                     "reg", &regp, &reglen);
 723 
 724                 if (rv != DDI_PROP_SUCCESS) {
 725                         goto nxge_attach_fail5;
 726                 }
 727                 /*
 728                  * The address_hi, that is the first int, in the reg
 729                  * property consists of config handle, but need to remove
 730                  * the bits 28-31 which are OBP specific info.
 731                  */
 732                 nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF;
 733                 ddi_prop_free(regp);
 734         }
 735 
 736         /*
 737          * Set the defaults for the MTU size.
 738          */
 739         nxge_hw_id_init(nxgep);
 740 
 741         if (isLDOMguest(nxgep)) {
 742                 uchar_t *prop_val;
 743                 uint_t prop_len;
 744                 uint32_t max_frame_size;
 745 
 746                 extern void nxge_get_logical_props(p_nxge_t);
 747 
 748                 nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR;
 749                 nxgep->mac.portmode = PORT_LOGICAL;
 750                 (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
 751                     "phy-type", "virtual transceiver");
 752 
 753                 nxgep->nports = 1;
 754                 nxgep->board_ver = 0;        /* XXX What? */
 755 
 756                 /*
 757                  * local-mac-address property gives us info on which
 758                  * specific MAC address the Hybrid resource is associated
 759                  * with.
 760                  */
 761                 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
 762                     "local-mac-address", &prop_val,
 763                     &prop_len) != DDI_PROP_SUCCESS) {
 764                         goto nxge_attach_fail5;
 765                 }
 766                 if (prop_len !=  ETHERADDRL) {
 767                         ddi_prop_free(prop_val);
 768                         goto nxge_attach_fail5;
 769                 }
 770                 ether_copy(prop_val, nxgep->hio_mac_addr);
 771                 ddi_prop_free(prop_val);
 772                 nxge_get_logical_props(nxgep);
 773 
 774                 /*
 775                  * Enable Jumbo property based on the "max-frame-size"
 776                  * property value.
 777                  */
 778                 max_frame_size = ddi_prop_get_int(DDI_DEV_T_ANY,
 779                     nxgep->dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
 780                     "max-frame-size", NXGE_MTU_DEFAULT_MAX);
 781                 if ((max_frame_size > NXGE_MTU_DEFAULT_MAX) &&
 782                     (max_frame_size <= TX_JUMBO_MTU)) {
 783                         nxgep->mac.is_jumbo = B_TRUE;
 784                         nxgep->mac.maxframesize = (uint16_t)max_frame_size;
 785                         nxgep->mac.default_mtu = nxgep->mac.maxframesize -
 786                             NXGE_EHEADER_VLAN_CRC;
 787                 }
 788         } else {
 789                 status = nxge_xcvr_find(nxgep);
 790 
 791                 if (status != NXGE_OK) {
 792                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: "
 793                             " Couldn't determine card type"
 794                             " .... exit "));
 795                         goto nxge_attach_fail5;
 796                 }
 797 
 798                 status = nxge_get_config_properties(nxgep);
 799 
 800                 if (status != NXGE_OK) {
 801                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 802                             "get_hw create failed"));
 803                         goto nxge_attach_fail;
 804                 }
 805         }
 806 
 807         /*
 808          * Setup the Kstats for the driver.
 809          */
 810         nxge_setup_kstats(nxgep);
 811 
 812         if (!isLDOMguest(nxgep))
 813                 nxge_setup_param(nxgep);
 814 
 815         status = nxge_setup_system_dma_pages(nxgep);
 816         if (status != NXGE_OK) {
 817                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed"));
 818                 goto nxge_attach_fail;
 819         }
 820 
 821 
 822         if (!isLDOMguest(nxgep))
 823                 nxge_hw_init_niu_common(nxgep);
 824 
 825         status = nxge_setup_mutexes(nxgep);
 826         if (status != NXGE_OK) {
 827                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed"));
 828                 goto nxge_attach_fail;
 829         }
 830 
 831 #if defined(sun4v)
 832         if (isLDOMguest(nxgep)) {
 833                 /* Find our VR & channel sets. */
 834                 status = nxge_hio_vr_add(nxgep);
 835                 if (status != DDI_SUCCESS) {
 836                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 837                             "nxge_hio_vr_add failed"));
 838                         (void) hsvc_unregister(&nxgep->niu_hsvc);
 839                         nxgep->niu_hsvc_available = B_FALSE;
 840                         goto nxge_attach_fail;
 841                 }
 842                 goto nxge_attach_exit;
 843         }
 844 #endif
 845 
 846         status = nxge_setup_dev(nxgep);
 847         if (status != DDI_SUCCESS) {
 848                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed"));
 849                 goto nxge_attach_fail;
 850         }
 851 
 852         status = nxge_add_intrs(nxgep);
 853         if (status != DDI_SUCCESS) {
 854                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed"));
 855                 goto nxge_attach_fail;
 856         }
 857 
 858         /* If a guest, register with vio_net instead. */
 859         if ((status = nxge_mac_register(nxgep)) != NXGE_OK) {
 860                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
 861                     "unable to register to mac layer (%d)", status));
 862                 goto nxge_attach_fail;
 863         }
 864 
 865         mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN);
 866 
 867         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
 868             "registered to mac (instance %d)", instance));
 869 
 870         /* nxge_link_monitor calls xcvr.check_link recursively */
 871         (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
 872 
 873         goto nxge_attach_exit;
 874 
 875 nxge_attach_fail:
 876         nxge_unattach(nxgep);
 877         goto nxge_attach_fail1;
 878 
 879 nxge_attach_fail5:
 880         /*
 881          * Tear down the ndd parameters setup.
 882          */
 883         nxge_destroy_param(nxgep);
 884 
 885         /*
 886          * Tear down the kstat setup.
 887          */
 888         nxge_destroy_kstats(nxgep);
 889 
 890 nxge_attach_fail4:
 891         if (nxgep->nxge_hw_p) {
 892                 nxge_uninit_common_dev(nxgep);
 893                 nxgep->nxge_hw_p = NULL;
 894         }
 895 
 896 nxge_attach_fail3:
 897         /*
 898          * Unmap the register setup.
 899          */
 900         nxge_unmap_regs(nxgep);
 901 
 902         nxge_fm_fini(nxgep);
 903 
 904 nxge_attach_fail2:
 905         ddi_soft_state_free(nxge_list, nxgep->instance);
 906 
 907 nxge_attach_fail1:
 908         if (status != NXGE_OK)
 909                 status = (NXGE_ERROR | NXGE_DDI_FAILED);
 910         nxgep = NULL;
 911 
 912 nxge_attach_exit:
 913         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x",
 914             status));
 915 
 916         return (status);
 917 }
 918 
 919 static int
 920 nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 921 {
 922         int             status = DDI_SUCCESS;
 923         int             instance;
 924         p_nxge_t        nxgep = NULL;
 925 
 926         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach"));
 927         instance = ddi_get_instance(dip);
 928         nxgep = ddi_get_soft_state(nxge_list, instance);
 929         if (nxgep == NULL) {
 930                 status = DDI_FAILURE;
 931                 goto nxge_detach_exit;
 932         }
 933 
 934         switch (cmd) {
 935         case DDI_DETACH:
 936                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH"));
 937                 break;
 938 
 939         case DDI_PM_SUSPEND:
 940                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
 941                 nxgep->suspended = DDI_PM_SUSPEND;
 942                 nxge_suspend(nxgep);
 943                 break;
 944 
 945         case DDI_SUSPEND:
 946                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND"));
 947                 if (nxgep->suspended != DDI_PM_SUSPEND) {
 948                         nxgep->suspended = DDI_SUSPEND;
 949                         nxge_suspend(nxgep);
 950                 }
 951                 break;
 952 
 953         default:
 954                 status = DDI_FAILURE;
 955         }
 956 
 957         if (cmd != DDI_DETACH)
 958                 goto nxge_detach_exit;
 959 
 960         /*
 961          * Stop the xcvr polling.
 962          */
 963         nxgep->suspended = cmd;
 964 
 965         (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
 966 
 967         if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) {
 968                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 969                     "<== nxge_detach status = 0x%08X", status));
 970                 return (DDI_FAILURE);
 971         }
 972 
 973         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
 974             "<== nxge_detach (mac_unregister) status = 0x%08X", status));
 975 
 976         nxge_unattach(nxgep);
 977         nxgep = NULL;
 978 
 979 nxge_detach_exit:
 980         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X",
 981             status));
 982 
 983         return (status);
 984 }
 985 
 986 static void
 987 nxge_unattach(p_nxge_t nxgep)
 988 {
 989         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach"));
 990 
 991         if (nxgep == NULL || nxgep->dev_regs == NULL) {
 992                 return;
 993         }
 994 
 995         nxgep->nxge_magic = 0;
 996 
 997         if (nxgep->nxge_timerid) {
 998                 nxge_stop_timer(nxgep, nxgep->nxge_timerid);
 999                 nxgep->nxge_timerid = 0;
1000         }
1001 
1002         /*
1003          * If this flag is set, it will affect the Neptune
1004          * only.
1005          */
1006         if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) {
1007                 nxge_niu_peu_reset(nxgep);
1008         }
1009 
1010 #if     defined(sun4v)
1011         if (isLDOMguest(nxgep)) {
1012                 (void) nxge_hio_vr_release(nxgep);
1013         }
1014 #endif
1015 
1016         if (nxgep->nxge_hw_p) {
1017                 nxge_uninit_common_dev(nxgep);
1018                 nxgep->nxge_hw_p = NULL;
1019         }
1020 
1021 #if     defined(sun4v)
1022         if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) {
1023                 (void) hsvc_unregister(&nxgep->niu_hsvc);
1024                 nxgep->niu_hsvc_available = B_FALSE;
1025         }
1026 #endif
1027         /*
1028          * Stop any further interrupts.
1029          */
1030         nxge_remove_intrs(nxgep);
1031 
1032         /*
1033          * Stop the device and free resources.
1034          */
1035         if (!isLDOMguest(nxgep)) {
1036                 nxge_destroy_dev(nxgep);
1037         }
1038 
1039         /*
1040          * Tear down the ndd parameters setup.
1041          */
1042         nxge_destroy_param(nxgep);
1043 
1044         /*
1045          * Tear down the kstat setup.
1046          */
1047         nxge_destroy_kstats(nxgep);
1048 
1049         /*
1050          * Free any memory allocated for PHY properties
1051          */
1052         if (nxgep->phy_prop.cnt > 0) {
1053                 KMEM_FREE(nxgep->phy_prop.arr,
1054                     sizeof (nxge_phy_mdio_val_t) * nxgep->phy_prop.cnt);
1055                 nxgep->phy_prop.cnt = 0;
1056         }
1057 
1058         /*
1059          * Destroy all mutexes.
1060          */
1061         nxge_destroy_mutexes(nxgep);
1062 
1063         /*
1064          * Remove the list of ndd parameters which
1065          * were setup during attach.
1066          */
1067         if (nxgep->dip) {
1068                 NXGE_DEBUG_MSG((nxgep, OBP_CTL,
1069                     " nxge_unattach: remove all properties"));
1070 
1071                 (void) ddi_prop_remove_all(nxgep->dip);
1072         }
1073 
1074 #if NXGE_PROPERTY
1075         nxge_remove_hard_properties(nxgep);
1076 #endif
1077 
1078         /*
1079          * Unmap the register setup.
1080          */
1081         nxge_unmap_regs(nxgep);
1082 
1083         nxge_fm_fini(nxgep);
1084 
1085         ddi_soft_state_free(nxge_list, nxgep->instance);
1086 
1087         NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach"));
1088 }
1089 
1090 #if defined(sun4v)
1091 int
1092 nxge_hsvc_register(nxge_t *nxgep)
1093 {
1094         nxge_status_t status;
1095         int i, j;
1096 
1097         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hsvc_register"));
1098         if (nxgep->niu_type != N2_NIU) {
1099                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hsvc_register"));
1100                 return (DDI_SUCCESS);
1101         }
1102 
1103         /*
1104          * Currently, the NIU Hypervisor API supports two major versions:
1105          * version 1 and 2.
1106          * If Hypervisor introduces a higher major or minor version,
1107          * please update NIU_MAJOR_HI and NIU_MINOR_HI accordingly.
1108          */
1109         nxgep->niu_hsvc_available = B_FALSE;
1110         bcopy(&niu_hsvc, &nxgep->niu_hsvc,
1111             sizeof (hsvc_info_t));
1112 
1113         for (i = NIU_MAJOR_HI; i > 0; i--) {
1114                 nxgep->niu_hsvc.hsvc_major = i;
1115                 for (j = NIU_MINOR_HI; j >= 0; j--) {
1116                         nxgep->niu_hsvc.hsvc_minor = j;
1117                         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1118                             "nxge_hsvc_register: %s: negotiating "
1119                             "hypervisor services revision %d "
1120                             "group: 0x%lx major: 0x%lx "
1121                             "minor: 0x%lx",
1122                             nxgep->niu_hsvc.hsvc_modname,
1123                             nxgep->niu_hsvc.hsvc_rev,
1124                             nxgep->niu_hsvc.hsvc_group,
1125                             nxgep->niu_hsvc.hsvc_major,
1126                             nxgep->niu_hsvc.hsvc_minor,
1127                             nxgep->niu_min_ver));
1128 
1129                         if ((status = hsvc_register(&nxgep->niu_hsvc,
1130                             &nxgep->niu_min_ver)) == 0) {
1131                                 /* Use the supported minor */
1132                                 nxgep->niu_hsvc.hsvc_minor = nxgep->niu_min_ver;
1133                                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1134                                     "nxge_hsvc_register: %s: negotiated "
1135                                     "hypervisor services revision %d "
1136                                     "group: 0x%lx major: 0x%lx "
1137                                     "minor: 0x%lx (niu_min_ver 0x%lx)",
1138                                     nxgep->niu_hsvc.hsvc_modname,
1139                                     nxgep->niu_hsvc.hsvc_rev,
1140                                     nxgep->niu_hsvc.hsvc_group,
1141                                     nxgep->niu_hsvc.hsvc_major,
1142                                     nxgep->niu_hsvc.hsvc_minor,
1143                                     nxgep->niu_min_ver));
1144 
1145                                 nxgep->niu_hsvc_available = B_TRUE;
1146                                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1147                                     "<== nxge_hsvc_register: "
1148                                     "NIU Hypervisor service enabled"));
1149                                 return (DDI_SUCCESS);
1150                         }
1151 
1152                         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1153                             "nxge_hsvc_register: %s: negotiated failed - "
1154                             "try lower major number "
1155                             "hypervisor services revision %d "
1156                             "group: 0x%lx major: 0x%lx minor: 0x%lx "
1157                             "errno: %d",
1158                             nxgep->niu_hsvc.hsvc_modname,
1159                             nxgep->niu_hsvc.hsvc_rev,
1160                             nxgep->niu_hsvc.hsvc_group,
1161                             nxgep->niu_hsvc.hsvc_major,
1162                             nxgep->niu_hsvc.hsvc_minor, status));
1163                 }
1164         }
1165 
1166         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1167             "nxge_hsvc_register: %s: cannot negotiate "
1168             "hypervisor services revision %d group: 0x%lx "
1169             "major: 0x%lx minor: 0x%lx errno: %d",
1170             niu_hsvc.hsvc_modname, niu_hsvc.hsvc_rev,
1171             niu_hsvc.hsvc_group, niu_hsvc.hsvc_major,
1172             niu_hsvc.hsvc_minor, status));
1173 
1174         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1175             "<== nxge_hsvc_register: Register to NIU Hypervisor failed"));
1176 
1177         return (DDI_FAILURE);
1178 }
1179 #endif
1180 
1181 static char n2_siu_name[] = "niu";
1182 
1183 static nxge_status_t
1184 nxge_map_regs(p_nxge_t nxgep)
1185 {
1186         int             ddi_status = DDI_SUCCESS;
1187         p_dev_regs_t    dev_regs;
1188         char            buf[MAXPATHLEN + 1];
1189         char            *devname;
1190 #ifdef  NXGE_DEBUG
1191         char            *sysname;
1192 #endif
1193         off_t           regsize;
1194         nxge_status_t   status = NXGE_OK;
1195 #if !defined(_BIG_ENDIAN)
1196         off_t pci_offset;
1197         uint16_t pcie_devctl;
1198 #endif
1199 
1200         if (isLDOMguest(nxgep)) {
1201                 return (nxge_guest_regs_map(nxgep));
1202         }
1203 
1204         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs"));
1205         nxgep->dev_regs = NULL;
1206         dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
1207         dev_regs->nxge_regh = NULL;
1208         dev_regs->nxge_pciregh = NULL;
1209         dev_regs->nxge_msix_regh = NULL;
1210         dev_regs->nxge_vir_regh = NULL;
1211         dev_regs->nxge_vir2_regh = NULL;
1212         nxgep->niu_type = NIU_TYPE_NONE;
1213 
1214         devname = ddi_pathname(nxgep->dip, buf);
1215         ASSERT(strlen(devname) > 0);
1216         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1217             "nxge_map_regs: pathname devname %s", devname));
1218 
1219         /*
1220          * The driver is running on a N2-NIU system if devname is something
1221          * like "/niu@80/network@0"
1222          */
1223         if (strstr(devname, n2_siu_name)) {
1224                 /* N2/NIU */
1225                 nxgep->niu_type = N2_NIU;
1226                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1227                     "nxge_map_regs: N2/NIU devname %s", devname));
1228                 /*
1229                  * Get function number:
1230                  *  - N2/NIU: "/niu@80/network@0" and "/niu@80/network@1"
1231                  */
1232                 nxgep->function_num =
1233                     (devname[strlen(devname) -1] == '1' ? 1 : 0);
1234                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1235                     "nxge_map_regs: N2/NIU function number %d",
1236                     nxgep->function_num));
1237         } else {
1238                 int             *prop_val;
1239                 uint_t          prop_len;
1240                 uint8_t         func_num;
1241 
1242                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip,
1243                     0, "reg",
1244                     &prop_val, &prop_len) != DDI_PROP_SUCCESS) {
1245                         NXGE_DEBUG_MSG((nxgep, VPD_CTL,
1246                             "Reg property not found"));
1247                         ddi_status = DDI_FAILURE;
1248                         goto nxge_map_regs_fail0;
1249 
1250                 } else {
1251                         func_num = (prop_val[0] >> 8) & 0x7;
1252                         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1253                             "Reg property found: fun # %d",
1254                             func_num));
1255                         nxgep->function_num = func_num;
1256                         if (isLDOMguest(nxgep)) {
1257                                 nxgep->function_num /= 2;
1258                                 return (NXGE_OK);
1259                         }
1260                         ddi_prop_free(prop_val);
1261                 }
1262         }
1263 
1264         switch (nxgep->niu_type) {
1265         default:
1266                 (void) ddi_dev_regsize(nxgep->dip, 0, &regsize);
1267                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1268                     "nxge_map_regs: pci config size 0x%x", regsize));
1269 
1270                 ddi_status = ddi_regs_map_setup(nxgep->dip, 0,
1271                     (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0,
1272                     &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh);
1273                 if (ddi_status != DDI_SUCCESS) {
1274                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1275                             "ddi_map_regs, nxge bus config regs failed"));
1276                         goto nxge_map_regs_fail0;
1277                 }
1278                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1279                     "nxge_map_reg: PCI config addr 0x%0llx "
1280                     " handle 0x%0llx", dev_regs->nxge_pciregp,
1281                     dev_regs->nxge_pciregh));
1282                         /*
1283                          * IMP IMP
1284                          * workaround  for bit swapping bug in HW
1285                          * which ends up in no-snoop = yes
1286                          * resulting, in DMA not synched properly
1287                          */
1288 #if !defined(_BIG_ENDIAN)
1289                 /* workarounds for x86 systems */
1290                 pci_offset = 0x80 + PCIE_DEVCTL;
1291                 pcie_devctl = pci_config_get16(dev_regs->nxge_pciregh,
1292                     pci_offset);
1293                 pcie_devctl &= ~PCIE_DEVCTL_ENABLE_NO_SNOOP;
1294                 pcie_devctl |= PCIE_DEVCTL_RO_EN;
1295                 pci_config_put16(dev_regs->nxge_pciregh, pci_offset,
1296                     pcie_devctl);
1297 #endif
1298 
1299                 (void) ddi_dev_regsize(nxgep->dip, 1, &regsize);
1300                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1301                     "nxge_map_regs: pio size 0x%x", regsize));
1302                 /* set up the device mapped register */
1303                 ddi_status = ddi_regs_map_setup(nxgep->dip, 1,
1304                     (caddr_t *)&(dev_regs->nxge_regp), 0, 0,
1305                     &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh);
1306                 if (ddi_status != DDI_SUCCESS) {
1307                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1308                             "ddi_map_regs for Neptune global reg failed"));
1309                         goto nxge_map_regs_fail1;
1310                 }
1311 
1312                 /* set up the msi/msi-x mapped register */
1313                 (void) ddi_dev_regsize(nxgep->dip, 2, &regsize);
1314                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1315                     "nxge_map_regs: msix size 0x%x", regsize));
1316                 ddi_status = ddi_regs_map_setup(nxgep->dip, 2,
1317                     (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0,
1318                     &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh);
1319                 if (ddi_status != DDI_SUCCESS) {
1320                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1321                             "ddi_map_regs for msi reg failed"));
1322                         goto nxge_map_regs_fail2;
1323                 }
1324 
1325                 /* set up the vio region mapped register */
1326                 (void) ddi_dev_regsize(nxgep->dip, 3, &regsize);
1327                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1328                     "nxge_map_regs: vio size 0x%x", regsize));
1329                 ddi_status = ddi_regs_map_setup(nxgep->dip, 3,
1330                     (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0,
1331                     &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh);
1332 
1333                 if (ddi_status != DDI_SUCCESS) {
1334                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1335                             "ddi_map_regs for nxge vio reg failed"));
1336                         goto nxge_map_regs_fail3;
1337                 }
1338                 nxgep->dev_regs = dev_regs;
1339 
1340                 NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh);
1341                 NPI_PCI_ADD_HANDLE_SET(nxgep,
1342                     (npi_reg_ptr_t)dev_regs->nxge_pciregp);
1343                 NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh);
1344                 NPI_MSI_ADD_HANDLE_SET(nxgep,
1345                     (npi_reg_ptr_t)dev_regs->nxge_msix_regp);
1346 
1347                 NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1348                 NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp);
1349 
1350                 NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1351                 NPI_REG_ADD_HANDLE_SET(nxgep,
1352                     (npi_reg_ptr_t)dev_regs->nxge_regp);
1353 
1354                 NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh);
1355                 NPI_VREG_ADD_HANDLE_SET(nxgep,
1356                     (npi_reg_ptr_t)dev_regs->nxge_vir_regp);
1357 
1358                 break;
1359 
1360         case N2_NIU:
1361                 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU"));
1362                 /*
1363                  * Set up the device mapped register (FWARC 2006/556)
1364                  * (changed back to 1: reg starts at 1!)
1365                  */
1366                 (void) ddi_dev_regsize(nxgep->dip, 1, &regsize);
1367                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1368                     "nxge_map_regs: dev size 0x%x", regsize));
1369                 ddi_status = ddi_regs_map_setup(nxgep->dip, 1,
1370                     (caddr_t *)&(dev_regs->nxge_regp), 0, 0,
1371                     &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh);
1372 
1373                 if (ddi_status != DDI_SUCCESS) {
1374                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1375                             "ddi_map_regs for N2/NIU, global reg failed "));
1376                         goto nxge_map_regs_fail1;
1377                 }
1378 
1379                 /* set up the first vio region mapped register */
1380                 (void) ddi_dev_regsize(nxgep->dip, 2, &regsize);
1381                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1382                     "nxge_map_regs: vio (1) size 0x%x", regsize));
1383                 ddi_status = ddi_regs_map_setup(nxgep->dip, 2,
1384                     (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0,
1385                     &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh);
1386 
1387                 if (ddi_status != DDI_SUCCESS) {
1388                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1389                             "ddi_map_regs for nxge vio reg failed"));
1390                         goto nxge_map_regs_fail2;
1391                 }
1392                 /* set up the second vio region mapped register */
1393                 (void) ddi_dev_regsize(nxgep->dip, 3, &regsize);
1394                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1395                     "nxge_map_regs: vio (3) size 0x%x", regsize));
1396                 ddi_status = ddi_regs_map_setup(nxgep->dip, 3,
1397                     (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0,
1398                     &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh);
1399 
1400                 if (ddi_status != DDI_SUCCESS) {
1401                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1402                             "ddi_map_regs for nxge vio2 reg failed"));
1403                         goto nxge_map_regs_fail3;
1404                 }
1405                 nxgep->dev_regs = dev_regs;
1406 
1407                 NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1408                 NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp);
1409 
1410                 NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1411                 NPI_REG_ADD_HANDLE_SET(nxgep,
1412                     (npi_reg_ptr_t)dev_regs->nxge_regp);
1413 
1414                 NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh);
1415                 NPI_VREG_ADD_HANDLE_SET(nxgep,
1416                     (npi_reg_ptr_t)dev_regs->nxge_vir_regp);
1417 
1418                 NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh);
1419                 NPI_V2REG_ADD_HANDLE_SET(nxgep,
1420                     (npi_reg_ptr_t)dev_regs->nxge_vir2_regp);
1421 
1422                 break;
1423         }
1424 
1425         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx "
1426             " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh));
1427 
1428         goto nxge_map_regs_exit;
1429 nxge_map_regs_fail3:
1430         if (dev_regs->nxge_msix_regh) {
1431                 ddi_regs_map_free(&dev_regs->nxge_msix_regh);
1432         }
1433         if (dev_regs->nxge_vir_regh) {
1434                 ddi_regs_map_free(&dev_regs->nxge_regh);
1435         }
1436 nxge_map_regs_fail2:
1437         if (dev_regs->nxge_regh) {
1438                 ddi_regs_map_free(&dev_regs->nxge_regh);
1439         }
1440 nxge_map_regs_fail1:
1441         if (dev_regs->nxge_pciregh) {
1442                 ddi_regs_map_free(&dev_regs->nxge_pciregh);
1443         }
1444 nxge_map_regs_fail0:
1445         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory"));
1446         kmem_free(dev_regs, sizeof (dev_regs_t));
1447 
1448 nxge_map_regs_exit:
1449         if (ddi_status != DDI_SUCCESS)
1450                 status |= (NXGE_ERROR | NXGE_DDI_FAILED);
1451         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs"));
1452         return (status);
1453 }
1454 
1455 static void
1456 nxge_unmap_regs(p_nxge_t nxgep)
1457 {
1458         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs"));
1459 
1460         if (isLDOMguest(nxgep)) {
1461                 nxge_guest_regs_map_free(nxgep);
1462                 return;
1463         }
1464 
1465         if (nxgep->dev_regs) {
1466                 if (nxgep->dev_regs->nxge_pciregh) {
1467                         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1468                             "==> nxge_unmap_regs: bus"));
1469                         ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh);
1470                         nxgep->dev_regs->nxge_pciregh = NULL;
1471                 }
1472                 if (nxgep->dev_regs->nxge_regh) {
1473                         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1474                             "==> nxge_unmap_regs: device registers"));
1475                         ddi_regs_map_free(&nxgep->dev_regs->nxge_regh);
1476                         nxgep->dev_regs->nxge_regh = NULL;
1477                 }
1478                 if (nxgep->dev_regs->nxge_msix_regh) {
1479                         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1480                             "==> nxge_unmap_regs: device interrupts"));
1481                         ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh);
1482                         nxgep->dev_regs->nxge_msix_regh = NULL;
1483                 }
1484                 if (nxgep->dev_regs->nxge_vir_regh) {
1485                         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1486                             "==> nxge_unmap_regs: vio region"));
1487                         ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh);
1488                         nxgep->dev_regs->nxge_vir_regh = NULL;
1489                 }
1490                 if (nxgep->dev_regs->nxge_vir2_regh) {
1491                         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1492                             "==> nxge_unmap_regs: vio2 region"));
1493                         ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh);
1494                         nxgep->dev_regs->nxge_vir2_regh = NULL;
1495                 }
1496 
1497                 kmem_free(nxgep->dev_regs, sizeof (dev_regs_t));
1498                 nxgep->dev_regs = NULL;
1499         }
1500 
1501         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs"));
1502 }
1503 
1504 static nxge_status_t
1505 nxge_setup_mutexes(p_nxge_t nxgep)
1506 {
1507         int ddi_status = DDI_SUCCESS;
1508         nxge_status_t status = NXGE_OK;
1509         nxge_classify_t *classify_ptr;
1510         int partition;
1511 
1512         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes"));
1513 
1514         /*
1515          * Get the interrupt cookie so the mutexes can be
1516          * Initialized.
1517          */
1518         if (isLDOMguest(nxgep)) {
1519                 nxgep->interrupt_cookie = 0;
1520         } else {
1521                 ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0,
1522                     &nxgep->interrupt_cookie);
1523 
1524                 if (ddi_status != DDI_SUCCESS) {
1525                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1526                             "<== nxge_setup_mutexes: failed 0x%x",
1527                             ddi_status));
1528                         goto nxge_setup_mutexes_exit;
1529                 }
1530         }
1531 
1532         cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL);
1533         MUTEX_INIT(&nxgep->poll_lock, NULL,
1534             MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1535 
1536         /*
1537          * Initialize mutexes for this device.
1538          */
1539         MUTEX_INIT(nxgep->genlock, NULL,
1540             MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1541         MUTEX_INIT(&nxgep->ouraddr_lock, NULL,
1542             MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1543         MUTEX_INIT(&nxgep->mif_lock, NULL,
1544             MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1545         MUTEX_INIT(&nxgep->group_lock, NULL,
1546             MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1547         RW_INIT(&nxgep->filter_lock, NULL,
1548             RW_DRIVER, (void *)nxgep->interrupt_cookie);
1549 
1550         classify_ptr = &nxgep->classifier;
1551                 /*
1552                  * FFLP Mutexes are never used in interrupt context
1553                  * as fflp operation can take very long time to
1554                  * complete and hence not suitable to invoke from interrupt
1555                  * handlers.
1556                  */
1557         MUTEX_INIT(&classify_ptr->tcam_lock, NULL,
1558             NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1559         if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
1560                 MUTEX_INIT(&classify_ptr->fcram_lock, NULL,
1561                     NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1562                 for (partition = 0; partition < MAX_PARTITION; partition++) {
1563                         MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL,
1564                             NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1565                 }
1566         }
1567 
1568 nxge_setup_mutexes_exit:
1569         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1570             "<== nxge_setup_mutexes status = %x", status));
1571 
1572         if (ddi_status != DDI_SUCCESS)
1573                 status |= (NXGE_ERROR | NXGE_DDI_FAILED);
1574 
1575         return (status);
1576 }
1577 
1578 static void
1579 nxge_destroy_mutexes(p_nxge_t nxgep)
1580 {
1581         int partition;
1582         nxge_classify_t *classify_ptr;
1583 
1584         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes"));
1585         RW_DESTROY(&nxgep->filter_lock);
1586         MUTEX_DESTROY(&nxgep->group_lock);
1587         MUTEX_DESTROY(&nxgep->mif_lock);
1588         MUTEX_DESTROY(&nxgep->ouraddr_lock);
1589         MUTEX_DESTROY(nxgep->genlock);
1590 
1591         classify_ptr = &nxgep->classifier;
1592         MUTEX_DESTROY(&classify_ptr->tcam_lock);
1593 
1594         /* Destroy all polling resources. */
1595         MUTEX_DESTROY(&nxgep->poll_lock);
1596         cv_destroy(&nxgep->poll_cv);
1597 
1598         /* free data structures, based on HW type */
1599         if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
1600                 MUTEX_DESTROY(&classify_ptr->fcram_lock);
1601                 for (partition = 0; partition < MAX_PARTITION; partition++) {
1602                         MUTEX_DESTROY(&classify_ptr->hash_lock[partition]);
1603                 }
1604         }
1605 
1606         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes"));
1607 }
1608 
1609 nxge_status_t
1610 nxge_init(p_nxge_t nxgep)
1611 {
1612         nxge_status_t status = NXGE_OK;
1613 
1614         NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init"));
1615 
1616         if (nxgep->drv_state & STATE_HW_INITIALIZED) {
1617                 return (status);
1618         }
1619 
1620         /*
1621          * Allocate system memory for the receive/transmit buffer blocks
1622          * and receive/transmit descriptor rings.
1623          */
1624         status = nxge_alloc_mem_pool(nxgep);
1625         if (status != NXGE_OK) {
1626                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n"));
1627                 goto nxge_init_fail1;
1628         }
1629 
1630         if (!isLDOMguest(nxgep)) {
1631                 /*
1632                  * Initialize and enable the TXC registers.
1633                  * (Globally enable the Tx controller,
1634                  *  enable the port, configure the dma channel bitmap,
1635                  *  configure the max burst size).
1636                  */
1637                 status = nxge_txc_init(nxgep);
1638                 if (status != NXGE_OK) {
1639                         NXGE_ERROR_MSG((nxgep,
1640                             NXGE_ERR_CTL, "init txc failed\n"));
1641                         goto nxge_init_fail2;
1642                 }
1643         }
1644 
1645         /*
1646          * Initialize and enable TXDMA channels.
1647          */
1648         status = nxge_init_txdma_channels(nxgep);
1649         if (status != NXGE_OK) {
1650                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n"));
1651                 goto nxge_init_fail3;
1652         }
1653 
1654         /*
1655          * Initialize and enable RXDMA channels.
1656          */
1657         status = nxge_init_rxdma_channels(nxgep);
1658         if (status != NXGE_OK) {
1659                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n"));
1660                 goto nxge_init_fail4;
1661         }
1662 
1663         /*
1664          * The guest domain is now done.
1665          */
1666         if (isLDOMguest(nxgep)) {
1667                 nxgep->drv_state |= STATE_HW_INITIALIZED;
1668                 goto nxge_init_exit;
1669         }
1670 
1671         /*
1672          * Initialize TCAM and FCRAM (Neptune).
1673          */
1674         status = nxge_classify_init(nxgep);
1675         if (status != NXGE_OK) {
1676                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n"));
1677                 goto nxge_init_fail5;
1678         }
1679 
1680         /*
1681          * Initialize ZCP
1682          */
1683         status = nxge_zcp_init(nxgep);
1684         if (status != NXGE_OK) {
1685                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n"));
1686                 goto nxge_init_fail5;
1687         }
1688 
1689         /*
1690          * Initialize IPP.
1691          */
1692         status = nxge_ipp_init(nxgep);
1693         if (status != NXGE_OK) {
1694                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n"));
1695                 goto nxge_init_fail5;
1696         }
1697 
1698         /*
1699          * Initialize the MAC block.
1700          */
1701         status = nxge_mac_init(nxgep);
1702         if (status != NXGE_OK) {
1703                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n"));
1704                 goto nxge_init_fail5;
1705         }
1706 
1707         /*
1708          * Enable the interrrupts for DDI.
1709          */
1710         nxge_intrs_enable(nxgep);
1711 
1712         nxgep->drv_state |= STATE_HW_INITIALIZED;
1713 
1714         goto nxge_init_exit;
1715 
1716 nxge_init_fail5:
1717         nxge_uninit_rxdma_channels(nxgep);
1718 nxge_init_fail4:
1719         nxge_uninit_txdma_channels(nxgep);
1720 nxge_init_fail3:
1721         if (!isLDOMguest(nxgep)) {
1722                 (void) nxge_txc_uninit(nxgep);
1723         }
1724 nxge_init_fail2:
1725         nxge_free_mem_pool(nxgep);
1726 nxge_init_fail1:
1727         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1728             "<== nxge_init status (failed) = 0x%08x", status));
1729         return (status);
1730 
1731 nxge_init_exit:
1732         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x",
1733             status));
1734         return (status);
1735 }
1736 
1737 
1738 timeout_id_t
1739 nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec)
1740 {
1741         if ((nxgep->suspended == 0) || (nxgep->suspended == DDI_RESUME)) {
1742                 return (timeout(func, (caddr_t)nxgep,
1743                     drv_usectohz(1000 * msec)));
1744         }
1745         return (NULL);
1746 }
1747 
1748 /*ARGSUSED*/
1749 void
1750 nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid)
1751 {
1752         if (timerid) {
1753                 (void) untimeout(timerid);
1754         }
1755 }
1756 
1757 void
1758 nxge_uninit(p_nxge_t nxgep)
1759 {
1760         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit"));
1761 
1762         if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
1763                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1764                     "==> nxge_uninit: not initialized"));
1765                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1766                     "<== nxge_uninit"));
1767                 return;
1768         }
1769 
1770         if (!isLDOMguest(nxgep)) {
1771                 /*
1772                  * Reset the receive MAC side.
1773                  */
1774                 (void) nxge_rx_mac_disable(nxgep);
1775 
1776                 /*
1777                  * Drain the IPP.
1778                  */
1779                 (void) nxge_ipp_drain(nxgep);
1780         }
1781 
1782         /* stop timer */
1783         if (nxgep->nxge_timerid) {
1784                 nxge_stop_timer(nxgep, nxgep->nxge_timerid);
1785                 nxgep->nxge_timerid = 0;
1786         }
1787 
1788         (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
1789         (void) nxge_intr_hw_disable(nxgep);
1790 
1791 
1792         /* Disable and soft reset the IPP */
1793         if (!isLDOMguest(nxgep))
1794                 (void) nxge_ipp_disable(nxgep);
1795 
1796         /* Free classification resources */
1797         (void) nxge_classify_uninit(nxgep);
1798 
1799         /*
1800          * Reset the transmit/receive DMA side.
1801          */
1802         (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
1803         (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
1804 
1805         nxge_uninit_txdma_channels(nxgep);
1806         nxge_uninit_rxdma_channels(nxgep);
1807 
1808         /*
1809          * Reset the transmit MAC side.
1810          */
1811         (void) nxge_tx_mac_disable(nxgep);
1812 
1813         nxge_free_mem_pool(nxgep);
1814 
1815         /*
1816          * Start the timer if the reset flag is not set.
1817          * If this reset flag is set, the link monitor
1818          * will not be started in order to stop furthur bus
1819          * activities coming from this interface.
1820          * The driver will start the monitor function
1821          * if the interface was initialized again later.
1822          */
1823         if (!nxge_peu_reset_enable) {
1824                 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
1825         }
1826 
1827         nxgep->drv_state &= ~STATE_HW_INITIALIZED;
1828 
1829         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: "
1830             "nxge_mblks_pending %d", nxge_mblks_pending));
1831 }
1832 
1833 void
1834 nxge_get64(p_nxge_t nxgep, p_mblk_t mp)
1835 {
1836         uint64_t        reg;
1837         uint64_t        regdata;
1838         int             i, retry;
1839 
1840         bcopy((char *)mp->b_rptr, (char *)&reg, sizeof (uint64_t));
1841         regdata = 0;
1842         retry = 1;
1843 
1844         for (i = 0; i < retry; i++) {
1845                 NXGE_REG_RD64(nxgep->npi_handle, reg, &regdata);
1846         }
1847         bcopy((char *)&regdata, (char *)mp->b_rptr, sizeof (uint64_t));
1848 }
1849 
1850 void
1851 nxge_put64(p_nxge_t nxgep, p_mblk_t mp)
1852 {
1853         uint64_t        reg;
1854         uint64_t        buf[2];
1855 
1856         bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t));
1857         reg = buf[0];
1858 
1859         NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]);
1860 }
1861 
1862 /*ARGSUSED*/
1863 /*VARARGS*/
1864 void
1865 nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...)
1866 {
1867         char msg_buffer[1048];
1868         char prefix_buffer[32];
1869         int instance;
1870         uint64_t debug_level;
1871         int cmn_level = CE_CONT;
1872         va_list ap;
1873 
1874         if (nxgep && nxgep->nxge_debug_level != nxge_debug_level) {
1875                 /* In case a developer has changed nxge_debug_level. */
1876                 if (nxgep->nxge_debug_level != nxge_debug_level)
1877                         nxgep->nxge_debug_level = nxge_debug_level;
1878         }
1879 
1880         debug_level = (nxgep == NULL) ? nxge_debug_level :
1881             nxgep->nxge_debug_level;
1882 
1883         if ((level & debug_level) ||
1884             (level == NXGE_NOTE) ||
1885             (level == NXGE_ERR_CTL)) {
1886                 /* do the msg processing */
1887                 MUTEX_ENTER(&nxgedebuglock);
1888 
1889                 if ((level & NXGE_NOTE)) {
1890                         cmn_level = CE_NOTE;
1891                 }
1892 
1893                 if (level & NXGE_ERR_CTL) {
1894                         cmn_level = CE_WARN;
1895                 }
1896 
1897                 va_start(ap, fmt);
1898                 (void) vsprintf(msg_buffer, fmt, ap);
1899                 va_end(ap);
1900                 if (nxgep == NULL) {
1901                         instance = -1;
1902                         (void) sprintf(prefix_buffer, "%s :", "nxge");
1903                 } else {
1904                         instance = nxgep->instance;
1905                         (void) sprintf(prefix_buffer,
1906                             "%s%d :", "nxge", instance);
1907                 }
1908 
1909                 MUTEX_EXIT(&nxgedebuglock);
1910                 cmn_err(cmn_level, "!%s %s\n",
1911                     prefix_buffer, msg_buffer);
1912 
1913         }
1914 }
1915 
1916 char *
1917 nxge_dump_packet(char *addr, int size)
1918 {
1919         uchar_t *ap = (uchar_t *)addr;
1920         int i;
1921         static char etherbuf[1024];
1922         char *cp = etherbuf;
1923         char digits[] = "0123456789abcdef";
1924 
1925         if (!size)
1926                 size = 60;
1927 
1928         if (size > MAX_DUMP_SZ) {
1929                 /* Dump the leading bytes */
1930                 for (i = 0; i < MAX_DUMP_SZ/2; i++) {
1931                         if (*ap > 0x0f)
1932                                 *cp++ = digits[*ap >> 4];
1933                         *cp++ = digits[*ap++ & 0xf];
1934                         *cp++ = ':';
1935                 }
1936                 for (i = 0; i < 20; i++)
1937                         *cp++ = '.';
1938                 /* Dump the last MAX_DUMP_SZ/2 bytes */
1939                 ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2));
1940                 for (i = 0; i < MAX_DUMP_SZ/2; i++) {
1941                         if (*ap > 0x0f)
1942                                 *cp++ = digits[*ap >> 4];
1943                         *cp++ = digits[*ap++ & 0xf];
1944                         *cp++ = ':';
1945                 }
1946         } else {
1947                 for (i = 0; i < size; i++) {
1948                         if (*ap > 0x0f)
1949                                 *cp++ = digits[*ap >> 4];
1950                         *cp++ = digits[*ap++ & 0xf];
1951                         *cp++ = ':';
1952                 }
1953         }
1954         *--cp = 0;
1955         return (etherbuf);
1956 }
1957 
1958 #ifdef  NXGE_DEBUG
1959 static void
1960 nxge_test_map_regs(p_nxge_t nxgep)
1961 {
1962         ddi_acc_handle_t cfg_handle;
1963         p_pci_cfg_t     cfg_ptr;
1964         ddi_acc_handle_t dev_handle;
1965         char            *dev_ptr;
1966         ddi_acc_handle_t pci_config_handle;
1967         uint32_t        regval;
1968         int             i;
1969 
1970         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs"));
1971 
1972         dev_handle = nxgep->dev_regs->nxge_regh;
1973         dev_ptr = (char *)nxgep->dev_regs->nxge_regp;
1974 
1975         if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
1976                 cfg_handle = nxgep->dev_regs->nxge_pciregh;
1977                 cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp;
1978 
1979                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1980                     "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr));
1981                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1982                     "Neptune PCI cfg_ptr vendor id ptr 0x%llx",
1983                     &cfg_ptr->vendorid));
1984                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1985                     "\tvendorid 0x%x devid 0x%x",
1986                     NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0),
1987                     NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid,    0)));
1988                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1989                     "PCI BAR: base 0x%x base14 0x%x base 18 0x%x "
1990                     "bar1c 0x%x",
1991                     NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base,   0),
1992                     NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0),
1993                     NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0),
1994                     NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0)));
1995                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1996                     "\nNeptune PCI BAR: base20 0x%x base24 0x%x "
1997                     "base 28 0x%x bar2c 0x%x\n",
1998                     NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0),
1999                     NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0),
2000                     NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0),
2001                     NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0)));
2002                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2003                     "\nNeptune PCI BAR: base30 0x%x\n",
2004                     NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0)));
2005 
2006                 cfg_handle = nxgep->dev_regs->nxge_pciregh;
2007                 cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp;
2008                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2009                     "first  0x%llx second 0x%llx third 0x%llx "
2010                     "last 0x%llx ",
2011                     NXGE_PIO_READ64(dev_handle,
2012                     (uint64_t *)(dev_ptr + 0),  0),
2013                     NXGE_PIO_READ64(dev_handle,
2014                     (uint64_t *)(dev_ptr + 8),  0),
2015                     NXGE_PIO_READ64(dev_handle,
2016                     (uint64_t *)(dev_ptr + 16), 0),
2017                     NXGE_PIO_READ64(cfg_handle,
2018                     (uint64_t *)(dev_ptr + 24), 0)));
2019         }
2020 }
2021 
2022 #endif
2023 
2024 static void
2025 nxge_suspend(p_nxge_t nxgep)
2026 {
2027         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend"));
2028 
2029         nxge_intrs_disable(nxgep);
2030         nxge_destroy_dev(nxgep);
2031 
2032         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend"));
2033 }
2034 
2035 static nxge_status_t
2036 nxge_resume(p_nxge_t nxgep)
2037 {
2038         nxge_status_t status = NXGE_OK;
2039 
2040         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume"));
2041 
2042         nxgep->suspended = DDI_RESUME;
2043         (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
2044         (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START);
2045         (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START);
2046         (void) nxge_rx_mac_enable(nxgep);
2047         (void) nxge_tx_mac_enable(nxgep);
2048         nxge_intrs_enable(nxgep);
2049         nxgep->suspended = 0;
2050 
2051         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2052             "<== nxge_resume status = 0x%x", status));
2053         return (status);
2054 }
2055 
2056 static nxge_status_t
2057 nxge_setup_dev(p_nxge_t nxgep)
2058 {
2059         nxge_status_t   status = NXGE_OK;
2060 
2061         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d",
2062             nxgep->mac.portnum));
2063 
2064         status = nxge_link_init(nxgep);
2065 
2066         if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) {
2067                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2068                     "port%d Bad register acc handle", nxgep->mac.portnum));
2069                 status = NXGE_ERROR;
2070         }
2071 
2072         if (status != NXGE_OK) {
2073                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2074                     " nxge_setup_dev status "
2075                     "(xcvr init 0x%08x)", status));
2076                 goto nxge_setup_dev_exit;
2077         }
2078 
2079 nxge_setup_dev_exit:
2080         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2081             "<== nxge_setup_dev port %d status = 0x%08x",
2082             nxgep->mac.portnum, status));
2083 
2084         return (status);
2085 }
2086 
2087 static void
2088 nxge_destroy_dev(p_nxge_t nxgep)
2089 {
2090         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev"));
2091 
2092         (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
2093 
2094         (void) nxge_hw_stop(nxgep);
2095 
2096         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev"));
2097 }
2098 
2099 static nxge_status_t
2100 nxge_setup_system_dma_pages(p_nxge_t nxgep)
2101 {
2102         int                     ddi_status = DDI_SUCCESS;
2103         uint_t                  count;
2104         ddi_dma_cookie_t        cookie;
2105         uint_t                  iommu_pagesize;
2106         nxge_status_t           status = NXGE_OK;
2107 
2108         NXGE_ERROR_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages"));
2109         nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1);
2110         if (nxgep->niu_type != N2_NIU) {
2111                 iommu_pagesize = dvma_pagesize(nxgep->dip);
2112                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2113                     " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
2114                     " default_block_size %d iommu_pagesize %d",
2115                     nxgep->sys_page_sz,
2116                     ddi_ptob(nxgep->dip, (ulong_t)1),
2117                     nxgep->rx_default_block_size,
2118                     iommu_pagesize));
2119 
2120                 if (iommu_pagesize != 0) {
2121                         if (nxgep->sys_page_sz == iommu_pagesize) {
2122                                 if (iommu_pagesize > 0x4000)
2123                                         nxgep->sys_page_sz = 0x4000;
2124                         } else {
2125                                 if (nxgep->sys_page_sz > iommu_pagesize)
2126                                         nxgep->sys_page_sz = iommu_pagesize;
2127                         }
2128                 }
2129         }
2130         nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1);
2131         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2132             "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
2133             "default_block_size %d page mask %d",
2134             nxgep->sys_page_sz,
2135             ddi_ptob(nxgep->dip, (ulong_t)1),
2136             nxgep->rx_default_block_size,
2137             nxgep->sys_page_mask));
2138 
2139 
2140         switch (nxgep->sys_page_sz) {
2141         default:
2142                 nxgep->sys_page_sz = 0x1000;
2143                 nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1);
2144                 nxgep->rx_default_block_size = 0x1000;
2145                 nxgep->rx_bksize_code = RBR_BKSIZE_4K;
2146                 break;
2147         case 0x1000:
2148                 nxgep->rx_default_block_size = 0x1000;
2149                 nxgep->rx_bksize_code = RBR_BKSIZE_4K;
2150                 break;
2151         case 0x2000:
2152                 nxgep->rx_default_block_size = 0x2000;
2153                 nxgep->rx_bksize_code = RBR_BKSIZE_8K;
2154                 break;
2155         case 0x4000:
2156                 nxgep->rx_default_block_size = 0x4000;
2157                 nxgep->rx_bksize_code = RBR_BKSIZE_16K;
2158                 break;
2159         case 0x8000:
2160                 nxgep->rx_default_block_size = 0x8000;
2161                 nxgep->rx_bksize_code = RBR_BKSIZE_32K;
2162                 break;
2163         }
2164 
2165 #ifndef USE_RX_BIG_BUF
2166         nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz;
2167 #else
2168                 nxgep->rx_default_block_size = 0x2000;
2169                 nxgep->rx_bksize_code = RBR_BKSIZE_8K;
2170 #endif
2171         /*
2172          * Get the system DMA burst size.
2173          */
2174         ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr,
2175             DDI_DMA_DONTWAIT, 0,
2176             &nxgep->dmasparehandle);
2177         if (ddi_status != DDI_SUCCESS) {
2178                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2179                     "ddi_dma_alloc_handle: failed "
2180                     " status 0x%x", ddi_status));
2181                 goto nxge_get_soft_properties_exit;
2182         }
2183 
2184         ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL,
2185             (caddr_t)nxgep->dmasparehandle,
2186             sizeof (nxgep->dmasparehandle),
2187             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2188             DDI_DMA_DONTWAIT, 0,
2189             &cookie, &count);
2190         if (ddi_status != DDI_DMA_MAPPED) {
2191                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2192                     "Binding spare handle to find system"
2193                     " burstsize failed."));
2194                 ddi_status = DDI_FAILURE;
2195                 goto nxge_get_soft_properties_fail1;
2196         }
2197 
2198         nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle);
2199         (void) ddi_dma_unbind_handle(nxgep->dmasparehandle);
2200 
2201 nxge_get_soft_properties_fail1:
2202         ddi_dma_free_handle(&nxgep->dmasparehandle);
2203 
2204 nxge_get_soft_properties_exit:
2205 
2206         if (ddi_status != DDI_SUCCESS)
2207                 status |= (NXGE_ERROR | NXGE_DDI_FAILED);
2208 
2209         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2210             "<== nxge_setup_system_dma_pages status = 0x%08x", status));
2211         return (status);
2212 }
2213 
2214 static nxge_status_t
2215 nxge_alloc_mem_pool(p_nxge_t nxgep)
2216 {
2217         nxge_status_t   status = NXGE_OK;
2218 
2219         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool"));
2220 
2221         status = nxge_alloc_rx_mem_pool(nxgep);
2222         if (status != NXGE_OK) {
2223                 return (NXGE_ERROR);
2224         }
2225 
2226         status = nxge_alloc_tx_mem_pool(nxgep);
2227         if (status != NXGE_OK) {
2228                 nxge_free_rx_mem_pool(nxgep);
2229                 return (NXGE_ERROR);
2230         }
2231 
2232         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool"));
2233         return (NXGE_OK);
2234 }
2235 
2236 static void
2237 nxge_free_mem_pool(p_nxge_t nxgep)
2238 {
2239         NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool"));
2240 
2241         nxge_free_rx_mem_pool(nxgep);
2242         nxge_free_tx_mem_pool(nxgep);
2243 
2244         NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool"));
2245 }
2246 
2247 nxge_status_t
2248 nxge_alloc_rx_mem_pool(p_nxge_t nxgep)
2249 {
2250         uint32_t                rdc_max;
2251         p_nxge_dma_pt_cfg_t     p_all_cfgp;
2252         p_nxge_hw_pt_cfg_t      p_cfgp;
2253         p_nxge_dma_pool_t       dma_poolp;
2254         p_nxge_dma_common_t     *dma_buf_p;
2255         p_nxge_dma_pool_t       dma_cntl_poolp;
2256         p_nxge_dma_common_t     *dma_cntl_p;
2257         uint32_t                *num_chunks; /* per dma */
2258         nxge_status_t           status = NXGE_OK;
2259 
2260         uint32_t                nxge_port_rbr_size;
2261         uint32_t                nxge_port_rbr_spare_size;
2262         uint32_t                nxge_port_rcr_size;
2263         uint32_t                rx_cntl_alloc_size;
2264 
2265         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool"));
2266 
2267         p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2268         p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
2269         rdc_max = NXGE_MAX_RDCS;
2270 
2271         /*
2272          * Allocate memory for the common DMA data structures.
2273          */
2274         dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t),
2275             KM_SLEEP);
2276         dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
2277             sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP);
2278 
2279         dma_cntl_poolp = (p_nxge_dma_pool_t)
2280             KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP);
2281         dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
2282             sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP);
2283 
2284         num_chunks = (uint32_t *)KMEM_ZALLOC(
2285             sizeof (uint32_t) * rdc_max, KM_SLEEP);
2286 
2287         /*
2288          * Assume that each DMA channel will be configured with
2289          * the default block size.
2290          * rbr block counts are modulo the batch count (16).
2291          */
2292         nxge_port_rbr_size = p_all_cfgp->rbr_size;
2293         nxge_port_rcr_size = p_all_cfgp->rcr_size;
2294 
2295         if (!nxge_port_rbr_size) {
2296                 nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT;
2297         }
2298         if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) {
2299                 nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH *
2300                     (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1));
2301         }
2302 
2303         p_all_cfgp->rbr_size = nxge_port_rbr_size;
2304         nxge_port_rbr_spare_size = nxge_rbr_spare_size;
2305 
2306         if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) {
2307                 nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH *
2308                     (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1));
2309         }
2310         if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) {
2311                 NXGE_DEBUG_MSG((nxgep, MEM_CTL,
2312                     "nxge_alloc_rx_mem_pool: RBR size too high %d, "
2313                     "set to default %d",
2314                     nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS));
2315                 nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS;
2316         }
2317         if (nxge_port_rcr_size > RCR_DEFAULT_MAX) {
2318                 NXGE_DEBUG_MSG((nxgep, MEM_CTL,
2319                     "nxge_alloc_rx_mem_pool: RCR too high %d, "
2320                     "set to default %d",
2321                     nxge_port_rcr_size, RCR_DEFAULT_MAX));
2322                 nxge_port_rcr_size = RCR_DEFAULT_MAX;
2323         }
2324 
2325         /*
2326          * N2/NIU has limitation on the descriptor sizes (contiguous
2327          * memory allocation on data buffers to 4M (contig_mem_alloc)
2328          * and little endian for control buffers (must use the ddi/dki mem alloc
2329          * function).
2330          */
2331 #if     defined(sun4v) && defined(NIU_LP_WORKAROUND)
2332         if (nxgep->niu_type == N2_NIU) {
2333                 nxge_port_rbr_spare_size = 0;
2334                 if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) ||
2335                     (!ISP2(nxge_port_rbr_size))) {
2336                         nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX;
2337                 }
2338                 if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) ||
2339                     (!ISP2(nxge_port_rcr_size))) {
2340                         nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX;
2341                 }
2342         }
2343 #endif
2344 
2345         /*
2346          * Addresses of receive block ring, receive completion ring and the
2347          * mailbox must be all cache-aligned (64 bytes).
2348          */
2349         rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size;
2350         rx_cntl_alloc_size *= (sizeof (rx_desc_t));
2351         rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size);
2352         rx_cntl_alloc_size += sizeof (rxdma_mailbox_t);
2353 
2354         NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: "
2355             "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d "
2356             "nxge_port_rcr_size = %d "
2357             "rx_cntl_alloc_size = %d",
2358             nxge_port_rbr_size, nxge_port_rbr_spare_size,
2359             nxge_port_rcr_size,
2360             rx_cntl_alloc_size));
2361 
2362 #if     defined(sun4v) && defined(NIU_LP_WORKAROUND)
2363         if (nxgep->niu_type == N2_NIU) {
2364                 uint32_t rx_buf_alloc_size = (nxgep->rx_default_block_size *
2365                     (nxge_port_rbr_size + nxge_port_rbr_spare_size));
2366 
2367                 if (!ISP2(rx_buf_alloc_size)) {
2368                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2369                             "==> nxge_alloc_rx_mem_pool: "
2370                             " must be power of 2"));
2371                         status |= (NXGE_ERROR | NXGE_DDI_FAILED);
2372                         goto nxge_alloc_rx_mem_pool_exit;
2373                 }
2374 
2375                 if (rx_buf_alloc_size > (1 << 22)) {
2376                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2377                             "==> nxge_alloc_rx_mem_pool: "
2378                             " limit size to 4M"));
2379                         status |= (NXGE_ERROR | NXGE_DDI_FAILED);
2380                         goto nxge_alloc_rx_mem_pool_exit;
2381                 }
2382 
2383                 if (rx_cntl_alloc_size < 0x2000) {
2384                         rx_cntl_alloc_size = 0x2000;
2385                 }
2386         }
2387 #endif
2388         nxgep->nxge_port_rbr_size = nxge_port_rbr_size;
2389         nxgep->nxge_port_rcr_size = nxge_port_rcr_size;
2390         nxgep->nxge_port_rbr_spare_size = nxge_port_rbr_spare_size;
2391         nxgep->nxge_port_rx_cntl_alloc_size = rx_cntl_alloc_size;
2392 
2393         dma_poolp->ndmas = p_cfgp->max_rdcs;
2394         dma_poolp->num_chunks = num_chunks;
2395         dma_poolp->buf_allocated = B_TRUE;
2396         nxgep->rx_buf_pool_p = dma_poolp;
2397         dma_poolp->dma_buf_pool_p = dma_buf_p;
2398 
2399         dma_cntl_poolp->ndmas = p_cfgp->max_rdcs;
2400         dma_cntl_poolp->buf_allocated = B_TRUE;
2401         nxgep->rx_cntl_pool_p = dma_cntl_poolp;
2402         dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
2403 
2404         /* Allocate the receive rings, too. */
2405         nxgep->rx_rbr_rings =
2406             KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP);
2407         nxgep->rx_rbr_rings->rbr_rings =
2408             KMEM_ZALLOC(sizeof (p_rx_rbr_ring_t) * rdc_max, KM_SLEEP);
2409         nxgep->rx_rcr_rings =
2410             KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP);
2411         nxgep->rx_rcr_rings->rcr_rings =
2412             KMEM_ZALLOC(sizeof (p_rx_rcr_ring_t) * rdc_max, KM_SLEEP);
2413         nxgep->rx_mbox_areas_p =
2414             KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP);
2415         nxgep->rx_mbox_areas_p->rxmbox_areas =
2416             KMEM_ZALLOC(sizeof (p_rx_mbox_t) * rdc_max, KM_SLEEP);
2417 
2418         nxgep->rx_rbr_rings->ndmas = nxgep->rx_rcr_rings->ndmas =
2419             p_cfgp->max_rdcs;
2420 
2421         NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2422             "<== nxge_alloc_rx_mem_pool:status 0x%08x", status));
2423 
2424 nxge_alloc_rx_mem_pool_exit:
2425         return (status);
2426 }
2427 
2428 /*
2429  * nxge_alloc_rxb
2430  *
2431  *      Allocate buffers for an RDC.
2432  *
2433  * Arguments:
2434  *      nxgep
2435  *      channel The channel to map into our kernel space.
2436  *
2437  * Notes:
2438  *
2439  * NPI function calls:
2440  *
2441  * NXGE function calls:
2442  *
2443  * Registers accessed:
2444  *
2445  * Context:
2446  *
2447  * Taking apart:
2448  *
2449  * Open questions:
2450  *
2451  */
2452 nxge_status_t
2453 nxge_alloc_rxb(
2454         p_nxge_t nxgep,
2455         int channel)
2456 {
2457         size_t                  rx_buf_alloc_size;
2458         nxge_status_t           status = NXGE_OK;
2459 
2460         nxge_dma_common_t       **data;
2461         nxge_dma_common_t       **control;
2462         uint32_t                *num_chunks;
2463 
2464         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb"));
2465 
2466         /*
2467          * Allocate memory for the receive buffers and descriptor rings.
2468          * Replace these allocation functions with the interface functions
2469          * provided by the partition manager if/when they are available.
2470          */
2471 
2472         /*
2473          * Allocate memory for the receive buffer blocks.
2474          */
2475         rx_buf_alloc_size = (nxgep->rx_default_block_size *
2476             (nxgep->nxge_port_rbr_size + nxgep->nxge_port_rbr_spare_size));
2477 
2478         data = &nxgep->rx_buf_pool_p->dma_buf_pool_p[channel];
2479         num_chunks = &nxgep->rx_buf_pool_p->num_chunks[channel];
2480 
2481         if ((status = nxge_alloc_rx_buf_dma(
2482             nxgep, channel, data, rx_buf_alloc_size,
2483             nxgep->rx_default_block_size, num_chunks)) != NXGE_OK) {
2484                 return (status);
2485         }
2486 
2487         NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_alloc_rxb(): "
2488             "dma %d dma_buf_p %llx &dma_buf_p %llx", channel, *data, data));
2489 
2490         /*
2491          * Allocate memory for descriptor rings and mailbox.
2492          */
2493         control = &nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel];
2494 
2495         if ((status = nxge_alloc_rx_cntl_dma(
2496             nxgep, channel, control, nxgep->nxge_port_rx_cntl_alloc_size))
2497             != NXGE_OK) {
2498                 nxge_free_rx_cntl_dma(nxgep, *control);
2499                 (*data)->buf_alloc_state |= BUF_ALLOCATED_WAIT_FREE;
2500                 nxge_free_rx_buf_dma(nxgep, *data, *num_chunks);
2501                 return (status);
2502         }
2503 
2504         NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2505             "<== nxge_alloc_rx_mem_pool:status 0x%08x", status));
2506 
2507         return (status);
2508 }
2509 
2510 void
2511 nxge_free_rxb(
2512         p_nxge_t nxgep,
2513         int channel)
2514 {
2515         nxge_dma_common_t       *data;
2516         nxge_dma_common_t       *control;
2517         uint32_t                num_chunks;
2518 
2519         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb"));
2520 
2521         data = nxgep->rx_buf_pool_p->dma_buf_pool_p[channel];
2522         num_chunks = nxgep->rx_buf_pool_p->num_chunks[channel];
2523         nxge_free_rx_buf_dma(nxgep, data, num_chunks);
2524 
2525         nxgep->rx_buf_pool_p->dma_buf_pool_p[channel] = 0;
2526         nxgep->rx_buf_pool_p->num_chunks[channel] = 0;
2527 
2528         control = nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel];
2529         nxge_free_rx_cntl_dma(nxgep, control);
2530 
2531         nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel] = 0;
2532 
2533         KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
2534         KMEM_FREE(control, sizeof (nxge_dma_common_t));
2535 
2536         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_alloc_rbb"));
2537 }
2538 
2539 static void
2540 nxge_free_rx_mem_pool(p_nxge_t nxgep)
2541 {
2542         int rdc_max = NXGE_MAX_RDCS;
2543 
2544         NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool"));
2545 
2546         if (!nxgep->rx_buf_pool_p || !nxgep->rx_buf_pool_p->buf_allocated) {
2547                 NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2548                     "<== nxge_free_rx_mem_pool "
2549                     "(null rx buf pool or buf not allocated"));
2550                 return;
2551         }
2552         if (!nxgep->rx_cntl_pool_p || !nxgep->rx_cntl_pool_p->buf_allocated) {
2553                 NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2554                     "<== nxge_free_rx_mem_pool "
2555                     "(null rx cntl buf pool or cntl buf not allocated"));
2556                 return;
2557         }
2558 
2559         KMEM_FREE(nxgep->rx_cntl_pool_p->dma_buf_pool_p,
2560             sizeof (p_nxge_dma_common_t) * rdc_max);
2561         KMEM_FREE(nxgep->rx_cntl_pool_p, sizeof (nxge_dma_pool_t));
2562 
2563         KMEM_FREE(nxgep->rx_buf_pool_p->num_chunks,
2564             sizeof (uint32_t) * rdc_max);
2565         KMEM_FREE(nxgep->rx_buf_pool_p->dma_buf_pool_p,
2566             sizeof (p_nxge_dma_common_t) * rdc_max);
2567         KMEM_FREE(nxgep->rx_buf_pool_p, sizeof (nxge_dma_pool_t));
2568 
2569         nxgep->rx_buf_pool_p = 0;
2570         nxgep->rx_cntl_pool_p = 0;
2571 
2572         KMEM_FREE(nxgep->rx_rbr_rings->rbr_rings,
2573             sizeof (p_rx_rbr_ring_t) * rdc_max);
2574         KMEM_FREE(nxgep->rx_rbr_rings, sizeof (rx_rbr_rings_t));
2575         KMEM_FREE(nxgep->rx_rcr_rings->rcr_rings,
2576             sizeof (p_rx_rcr_ring_t) * rdc_max);
2577         KMEM_FREE(nxgep->rx_rcr_rings, sizeof (rx_rcr_rings_t));
2578         KMEM_FREE(nxgep->rx_mbox_areas_p->rxmbox_areas,
2579             sizeof (p_rx_mbox_t) * rdc_max);
2580         KMEM_FREE(nxgep->rx_mbox_areas_p, sizeof (rx_mbox_areas_t));
2581 
2582         nxgep->rx_rbr_rings = 0;
2583         nxgep->rx_rcr_rings = 0;
2584         nxgep->rx_mbox_areas_p = 0;
2585 
2586         NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool"));
2587 }
2588 
2589 
2590 static nxge_status_t
2591 nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel,
2592         p_nxge_dma_common_t *dmap,
2593         size_t alloc_size, size_t block_size, uint32_t *num_chunks)
2594 {
2595         p_nxge_dma_common_t     rx_dmap;
2596         nxge_status_t           status = NXGE_OK;
2597         size_t                  total_alloc_size;
2598         size_t                  allocated = 0;
2599         int                     i, size_index, array_size;
2600         boolean_t               use_kmem_alloc = B_FALSE;
2601 
2602         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma"));
2603 
2604         rx_dmap = (p_nxge_dma_common_t)
2605             KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK,
2606             KM_SLEEP);
2607 
2608         NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2609             " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ",
2610             dma_channel, alloc_size, block_size, dmap));
2611 
2612         total_alloc_size = alloc_size;
2613 
2614 #if defined(RX_USE_RECLAIM_POST)
2615         total_alloc_size = alloc_size + alloc_size/4;
2616 #endif
2617 
2618         i = 0;
2619         size_index = 0;
2620         array_size =  sizeof (alloc_sizes)/sizeof (size_t);
2621         while ((size_index < array_size) &&
2622             (alloc_sizes[size_index] < alloc_size))
2623                 size_index++;
2624         if (size_index >= array_size) {
2625                 size_index = array_size - 1;
2626         }
2627 
2628         /* For Neptune, use kmem_alloc if the kmem flag is set. */
2629         if (nxgep->niu_type != N2_NIU && nxge_use_kmem_alloc) {
2630                 use_kmem_alloc = B_TRUE;
2631 #if defined(__i386) || defined(__amd64)
2632                 size_index = 0;
2633 #endif
2634                 NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2635                     "==> nxge_alloc_rx_buf_dma: "
2636                     "Neptune use kmem_alloc() - size_index %d",
2637                     size_index));
2638         }
2639 
2640         while ((allocated < total_alloc_size) &&
2641             (size_index >= 0) && (i < NXGE_DMA_BLOCK)) {
2642                 rx_dmap[i].dma_chunk_index = i;
2643                 rx_dmap[i].block_size = block_size;
2644                 rx_dmap[i].alength = alloc_sizes[size_index];
2645                 rx_dmap[i].orig_alength = rx_dmap[i].alength;
2646                 rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
2647                 rx_dmap[i].dma_channel = dma_channel;
2648                 rx_dmap[i].contig_alloc_type = B_FALSE;
2649                 rx_dmap[i].kmem_alloc_type = B_FALSE;
2650                 rx_dmap[i].buf_alloc_type = DDI_MEM_ALLOC;
2651 
2652                 /*
2653                  * N2/NIU: data buffers must be contiguous as the driver
2654                  *         needs to call Hypervisor api to set up
2655                  *         logical pages.
2656                  */
2657                 if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) {
2658                         rx_dmap[i].contig_alloc_type = B_TRUE;
2659                         rx_dmap[i].buf_alloc_type = CONTIG_MEM_ALLOC;
2660                 } else if (use_kmem_alloc) {
2661                         /* For Neptune, use kmem_alloc */
2662                         NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2663                             "==> nxge_alloc_rx_buf_dma: "
2664                             "Neptune use kmem_alloc()"));
2665                         rx_dmap[i].kmem_alloc_type = B_TRUE;
2666                         rx_dmap[i].buf_alloc_type = KMEM_ALLOC;
2667                 }
2668 
2669                 NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2670                     "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x "
2671                     "i %d nblocks %d alength %d",
2672                     dma_channel, i, &rx_dmap[i], block_size,
2673                     i, rx_dmap[i].nblocks,
2674                     rx_dmap[i].alength));
2675                 status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
2676                     &nxge_rx_dma_attr,
2677                     rx_dmap[i].alength,
2678                     &nxge_dev_buf_dma_acc_attr,
2679                     DDI_DMA_READ | DDI_DMA_STREAMING,
2680                     (p_nxge_dma_common_t)(&rx_dmap[i]));
2681                 if (status != NXGE_OK) {
2682                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2683                             "nxge_alloc_rx_buf_dma: Alloc Failed: "
2684                             "dma %d size_index %d size requested %d",
2685                             dma_channel,
2686                             size_index,
2687                             rx_dmap[i].alength));
2688                         size_index--;
2689                 } else {
2690                         rx_dmap[i].buf_alloc_state = BUF_ALLOCATED;
2691                         NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2692                             " nxge_alloc_rx_buf_dma DONE  alloc mem: "
2693                             "dma %d dma_buf_p $%p kaddrp $%p alength %d "
2694                             "buf_alloc_state %d alloc_type %d",
2695                             dma_channel,
2696                             &rx_dmap[i],
2697                             rx_dmap[i].kaddrp,
2698                             rx_dmap[i].alength,
2699                             rx_dmap[i].buf_alloc_state,
2700                             rx_dmap[i].buf_alloc_type));
2701                         NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2702                             " alloc_rx_buf_dma allocated rdc %d "
2703                             "chunk %d size %x dvma %x bufp %llx kaddrp $%p",
2704                             dma_channel, i, rx_dmap[i].alength,
2705                             rx_dmap[i].ioaddr_pp, &rx_dmap[i],
2706                             rx_dmap[i].kaddrp));
2707                         i++;
2708                         allocated += alloc_sizes[size_index];
2709                 }
2710         }
2711 
2712         if (allocated < total_alloc_size) {
2713                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2714                     "==> nxge_alloc_rx_buf_dma: not enough for channel %d "
2715                     "allocated 0x%x requested 0x%x",
2716                     dma_channel,
2717                     allocated, total_alloc_size));
2718                 status = NXGE_ERROR;
2719                 goto nxge_alloc_rx_mem_fail1;
2720         }
2721 
2722         NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2723             "==> nxge_alloc_rx_buf_dma: Allocated for channel %d "
2724             "allocated 0x%x requested 0x%x",
2725             dma_channel,
2726             allocated, total_alloc_size));
2727 
2728         NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2729             " alloc_rx_buf_dma rdc %d allocated %d chunks",
2730             dma_channel, i));
2731         *num_chunks = i;
2732         *dmap = rx_dmap;
2733 
2734         goto nxge_alloc_rx_mem_exit;
2735 
2736 nxge_alloc_rx_mem_fail1:
2737         KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
2738 
2739 nxge_alloc_rx_mem_exit:
2740         NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2741             "<== nxge_alloc_rx_buf_dma status 0x%08x", status));
2742 
2743         return (status);
2744 }
2745 
2746 /*ARGSUSED*/
2747 static void
2748 nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap,
2749     uint32_t num_chunks)
2750 {
2751         int             i;
2752 
2753         NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2754             "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks));
2755 
2756         if (dmap == 0)
2757                 return;
2758 
2759         for (i = 0; i < num_chunks; i++) {
2760                 NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2761                     "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx",
2762                     i, dmap));
2763                 nxge_dma_free_rx_data_buf(dmap++);
2764         }
2765 
2766         NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma"));
2767 }
2768 
2769 /*ARGSUSED*/
2770 static nxge_status_t
2771 nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel,
2772     p_nxge_dma_common_t *dmap, size_t size)
2773 {
2774         p_nxge_dma_common_t     rx_dmap;
2775         nxge_status_t           status = NXGE_OK;
2776 
2777         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma"));
2778 
2779         rx_dmap = (p_nxge_dma_common_t)
2780             KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP);
2781 
2782         rx_dmap->contig_alloc_type = B_FALSE;
2783         rx_dmap->kmem_alloc_type = B_FALSE;
2784 
2785         status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
2786             &nxge_desc_dma_attr,
2787             size,
2788             &nxge_dev_desc_dma_acc_attr,
2789             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2790             rx_dmap);
2791         if (status != NXGE_OK) {
2792                 goto nxge_alloc_rx_cntl_dma_fail1;
2793         }
2794 
2795         *dmap = rx_dmap;
2796         goto nxge_alloc_rx_cntl_dma_exit;
2797 
2798 nxge_alloc_rx_cntl_dma_fail1:
2799         KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t));
2800 
2801 nxge_alloc_rx_cntl_dma_exit:
2802         NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2803             "<== nxge_alloc_rx_cntl_dma status 0x%08x", status));
2804 
2805         return (status);
2806 }
2807 
2808 /*ARGSUSED*/
2809 static void
2810 nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap)
2811 {
2812         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma"));
2813 
2814         if (dmap == 0)
2815                 return;
2816 
2817         nxge_dma_mem_free(dmap);
2818 
2819         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma"));
2820 }
2821 
2822 typedef struct {
2823         size_t  tx_size;
2824         size_t  cr_size;
2825         size_t  threshhold;
2826 } nxge_tdc_sizes_t;
2827 
2828 static
2829 nxge_status_t
2830 nxge_tdc_sizes(
2831         nxge_t *nxgep,
2832         nxge_tdc_sizes_t *sizes)
2833 {
2834         uint32_t threshhold;    /* The bcopy() threshhold */
2835         size_t tx_size;         /* Transmit buffer size */
2836         size_t cr_size;         /* Completion ring size */
2837 
2838         /*
2839          * Assume that each DMA channel will be configured with the
2840          * default transmit buffer size for copying transmit data.
2841          * (If a packet is bigger than this, it will not be copied.)
2842          */
2843         if (nxgep->niu_type == N2_NIU) {
2844                 threshhold = TX_BCOPY_SIZE;
2845         } else {
2846                 threshhold = nxge_bcopy_thresh;
2847         }
2848         tx_size = nxge_tx_ring_size * threshhold;
2849 
2850         cr_size = nxge_tx_ring_size * sizeof (tx_desc_t);
2851         cr_size += sizeof (txdma_mailbox_t);
2852 
2853 #if     defined(sun4v) && defined(NIU_LP_WORKAROUND)
2854         if (nxgep->niu_type == N2_NIU) {
2855                 if (!ISP2(tx_size)) {
2856                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2857                             "==> nxge_tdc_sizes: Tx size"
2858                             " must be power of 2"));
2859                         return (NXGE_ERROR);
2860                 }
2861 
2862                 if (tx_size > (1 << 22)) {
2863                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2864                             "==> nxge_tdc_sizes: Tx size"
2865                             " limited to 4M"));
2866                         return (NXGE_ERROR);
2867                 }
2868 
2869                 if (cr_size < 0x2000)
2870                         cr_size = 0x2000;
2871         }
2872 #endif
2873 
2874         sizes->threshhold = threshhold;
2875         sizes->tx_size = tx_size;
2876         sizes->cr_size = cr_size;
2877 
2878         return (NXGE_OK);
2879 }
2880 /*
2881  * nxge_alloc_txb
2882  *
2883  *      Allocate buffers for an TDC.
2884  *
2885  * Arguments:
2886  *      nxgep
2887  *      channel The channel to map into our kernel space.
2888  *
2889  * Notes:
2890  *
2891  * NPI function calls:
2892  *
2893  * NXGE function calls:
2894  *
2895  * Registers accessed:
2896  *
2897  * Context:
2898  *
2899  * Taking apart:
2900  *
2901  * Open questions:
2902  *
2903  */
2904 nxge_status_t
2905 nxge_alloc_txb(
2906         p_nxge_t nxgep,
2907         int channel)
2908 {
2909         nxge_dma_common_t       **dma_buf_p;
2910         nxge_dma_common_t       **dma_cntl_p;
2911         uint32_t                *num_chunks;
2912         nxge_status_t           status = NXGE_OK;
2913 
2914         nxge_tdc_sizes_t        sizes;
2915 
2916         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tbb"));
2917 
2918         if (nxge_tdc_sizes(nxgep, &sizes) != NXGE_OK)
2919                 return (NXGE_ERROR);
2920 
2921         /*
2922          * Allocate memory for transmit buffers and descriptor rings.
2923          * Replace these allocation functions with the interface functions
2924          * provided by the partition manager Real Soon Now.
2925          */
2926         dma_buf_p = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel];
2927         num_chunks = &nxgep->tx_buf_pool_p->num_chunks[channel];
2928 
2929         dma_cntl_p = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel];
2930 
2931         /*
2932          * Allocate memory for transmit buffers and descriptor rings.
2933          * Replace allocation functions with interface functions provided
2934          * by the partition manager when it is available.
2935          *
2936          * Allocate memory for the transmit buffer pool.
2937          */
2938         NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2939             "sizes: tx: %ld, cr:%ld, th:%ld",
2940             sizes.tx_size, sizes.cr_size, sizes.threshhold));
2941 
2942         *num_chunks = 0;
2943         status = nxge_alloc_tx_buf_dma(nxgep, channel, dma_buf_p,
2944             sizes.tx_size, sizes.threshhold, num_chunks);
2945         if (status != NXGE_OK) {
2946                 cmn_err(CE_NOTE, "nxge_alloc_tx_buf_dma failed!");
2947                 return (status);
2948         }
2949 
2950         /*
2951          * Allocate memory for descriptor rings and mailbox.
2952          */
2953         status = nxge_alloc_tx_cntl_dma(nxgep, channel, dma_cntl_p,
2954             sizes.cr_size);
2955         if (status != NXGE_OK) {
2956                 nxge_free_tx_buf_dma(nxgep, *dma_buf_p, *num_chunks);
2957                 cmn_err(CE_NOTE, "nxge_alloc_tx_cntl_dma failed!");
2958                 return (status);
2959         }
2960 
2961         return (NXGE_OK);
2962 }
2963 
2964 void
2965 nxge_free_txb(
2966         p_nxge_t nxgep,
2967         int channel)
2968 {
2969         nxge_dma_common_t       *data;
2970         nxge_dma_common_t       *control;
2971         uint32_t                num_chunks;
2972 
2973         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_txb"));
2974 
2975         data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel];
2976         num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel];
2977         nxge_free_tx_buf_dma(nxgep, data, num_chunks);
2978 
2979         nxgep->tx_buf_pool_p->dma_buf_pool_p[channel] = 0;
2980         nxgep->tx_buf_pool_p->num_chunks[channel] = 0;
2981 
2982         control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel];
2983         nxge_free_tx_cntl_dma(nxgep, control);
2984 
2985         nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel] = 0;
2986 
2987         KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
2988         KMEM_FREE(control, sizeof (nxge_dma_common_t));
2989 
2990         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_txb"));
2991 }
2992 
2993 /*
2994  * nxge_alloc_tx_mem_pool
2995  *
2996  *      This function allocates all of the per-port TDC control data structures.
2997  *      The per-channel (TDC) data structures are allocated when needed.
2998  *
2999  * Arguments:
3000  *      nxgep
3001  *
3002  * Notes:
3003  *
3004  * Context:
3005  *      Any domain
3006  */
3007 nxge_status_t
3008 nxge_alloc_tx_mem_pool(p_nxge_t nxgep)
3009 {
3010         nxge_hw_pt_cfg_t        *p_cfgp;
3011         nxge_dma_pool_t         *dma_poolp;
3012         nxge_dma_common_t       **dma_buf_p;
3013         nxge_dma_pool_t         *dma_cntl_poolp;
3014         nxge_dma_common_t       **dma_cntl_p;
3015         uint32_t                *num_chunks; /* per dma */
3016         int                     tdc_max;
3017 
3018         NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool"));
3019 
3020         p_cfgp = &nxgep->pt_config.hw_config;
3021         tdc_max = NXGE_MAX_TDCS;
3022 
3023         /*
3024          * Allocate memory for each transmit DMA channel.
3025          */
3026         dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t),
3027             KM_SLEEP);
3028         dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
3029             sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP);
3030 
3031         dma_cntl_poolp = (p_nxge_dma_pool_t)
3032             KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP);
3033         dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
3034             sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP);
3035 
3036         if (nxge_tx_ring_size > TDC_DEFAULT_MAX) {
3037                 NXGE_DEBUG_MSG((nxgep, MEM_CTL,
3038                     "nxge_alloc_tx_mem_pool: TDC too high %d, "
3039                     "set to default %d",
3040                     nxge_tx_ring_size, TDC_DEFAULT_MAX));
3041                 nxge_tx_ring_size = TDC_DEFAULT_MAX;
3042         }
3043 
3044 #if     defined(sun4v) && defined(NIU_LP_WORKAROUND)
3045         /*
3046          * N2/NIU has limitation on the descriptor sizes (contiguous
3047          * memory allocation on data buffers to 4M (contig_mem_alloc)
3048          * and little endian for control buffers (must use the ddi/dki mem alloc
3049          * function). The transmit ring is limited to 8K (includes the
3050          * mailbox).
3051          */
3052         if (nxgep->niu_type == N2_NIU) {
3053                 if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) ||
3054                     (!ISP2(nxge_tx_ring_size))) {
3055                         nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX;
3056                 }
3057         }
3058 #endif
3059 
3060         nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size;
3061 
3062         num_chunks = (uint32_t *)KMEM_ZALLOC(
3063             sizeof (uint32_t) * tdc_max, KM_SLEEP);
3064 
3065         dma_poolp->ndmas = p_cfgp->tdc.owned;
3066         dma_poolp->num_chunks = num_chunks;
3067         dma_poolp->dma_buf_pool_p = dma_buf_p;
3068         nxgep->tx_buf_pool_p = dma_poolp;
3069 
3070         dma_poolp->buf_allocated = B_TRUE;
3071 
3072         dma_cntl_poolp->ndmas = p_cfgp->tdc.owned;
3073         dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
3074         nxgep->tx_cntl_pool_p = dma_cntl_poolp;
3075 
3076         dma_cntl_poolp->buf_allocated = B_TRUE;
3077 
3078         nxgep->tx_rings =
3079             KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP);
3080         nxgep->tx_rings->rings =
3081             KMEM_ZALLOC(sizeof (p_tx_ring_t) * tdc_max, KM_SLEEP);
3082         nxgep->tx_mbox_areas_p =
3083             KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP);
3084         nxgep->tx_mbox_areas_p->txmbox_areas_p =
3085             KMEM_ZALLOC(sizeof (p_tx_mbox_t) * tdc_max, KM_SLEEP);
3086 
3087         nxgep->tx_rings->ndmas = p_cfgp->tdc.owned;
3088 
3089         NXGE_DEBUG_MSG((nxgep, MEM_CTL,
3090             "==> nxge_alloc_tx_mem_pool: ndmas %d poolp->ndmas %d",
3091             tdc_max, dma_poolp->ndmas));
3092 
3093         return (NXGE_OK);
3094 }
3095 
3096 nxge_status_t
3097 nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel,
3098     p_nxge_dma_common_t *dmap, size_t alloc_size,
3099     size_t block_size, uint32_t *num_chunks)
3100 {
3101         p_nxge_dma_common_t     tx_dmap;
3102         nxge_status_t           status = NXGE_OK;
3103         size_t                  total_alloc_size;
3104         size_t                  allocated = 0;
3105         int                     i, size_index, array_size;
3106 
3107         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma"));
3108 
3109         tx_dmap = (p_nxge_dma_common_t)
3110             KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK,
3111             KM_SLEEP);
3112 
3113         total_alloc_size = alloc_size;
3114         i = 0;
3115         size_index = 0;
3116         array_size =  sizeof (alloc_sizes) /  sizeof (size_t);
3117         while ((size_index < array_size) &&
3118             (alloc_sizes[size_index] < alloc_size))
3119                 size_index++;
3120         if (size_index >= array_size) {
3121                 size_index = array_size - 1;
3122         }
3123 
3124         while ((allocated < total_alloc_size) &&
3125             (size_index >= 0) && (i < NXGE_DMA_BLOCK)) {
3126 
3127                 tx_dmap[i].dma_chunk_index = i;
3128                 tx_dmap[i].block_size = block_size;
3129                 tx_dmap[i].alength = alloc_sizes[size_index];
3130                 tx_dmap[i].orig_alength = tx_dmap[i].alength;
3131                 tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
3132                 tx_dmap[i].dma_channel = dma_channel;
3133                 tx_dmap[i].contig_alloc_type = B_FALSE;
3134                 tx_dmap[i].kmem_alloc_type = B_FALSE;
3135 
3136                 /*
3137                  * N2/NIU: data buffers must be contiguous as the driver
3138                  *         needs to call Hypervisor api to set up
3139                  *         logical pages.
3140                  */
3141                 if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) {
3142                         tx_dmap[i].contig_alloc_type = B_TRUE;
3143                 }
3144 
3145                 status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
3146                     &nxge_tx_dma_attr,
3147                     tx_dmap[i].alength,
3148                     &nxge_dev_buf_dma_acc_attr,
3149                     DDI_DMA_WRITE | DDI_DMA_STREAMING,
3150                     (p_nxge_dma_common_t)(&tx_dmap[i]));
3151                 if (status != NXGE_OK) {
3152                         size_index--;
3153                 } else {
3154                         i++;
3155                         allocated += alloc_sizes[size_index];
3156                 }
3157         }
3158 
3159         if (allocated < total_alloc_size) {
3160                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3161                     "==> nxge_alloc_tx_buf_dma: not enough channel %d: "
3162                     "allocated 0x%x requested 0x%x",
3163                     dma_channel,
3164                     allocated, total_alloc_size));
3165                 status = NXGE_ERROR;
3166                 goto nxge_alloc_tx_mem_fail1;
3167         }
3168 
3169         NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
3170             "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: "
3171             "allocated 0x%x requested 0x%x",
3172             dma_channel,
3173             allocated, total_alloc_size));
3174 
3175         *num_chunks = i;
3176         *dmap = tx_dmap;
3177         NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3178             "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d",
3179             *dmap, i));
3180         goto nxge_alloc_tx_mem_exit;
3181 
3182 nxge_alloc_tx_mem_fail1:
3183         KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
3184 
3185 nxge_alloc_tx_mem_exit:
3186         NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3187             "<== nxge_alloc_tx_buf_dma status 0x%08x", status));
3188 
3189         return (status);
3190 }
3191 
3192 /*ARGSUSED*/
3193 static void
3194 nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap,
3195     uint32_t num_chunks)
3196 {
3197         int             i;
3198 
3199         NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma"));
3200 
3201         if (dmap == 0)
3202                 return;
3203 
3204         for (i = 0; i < num_chunks; i++) {
3205                 nxge_dma_mem_free(dmap++);
3206         }
3207 
3208         NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma"));
3209 }
3210 
3211 /*ARGSUSED*/
3212 nxge_status_t
3213 nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel,
3214     p_nxge_dma_common_t *dmap, size_t size)
3215 {
3216         p_nxge_dma_common_t     tx_dmap;
3217         nxge_status_t           status = NXGE_OK;
3218 
3219         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma"));
3220         tx_dmap = (p_nxge_dma_common_t)
3221             KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP);
3222 
3223         tx_dmap->contig_alloc_type = B_FALSE;
3224         tx_dmap->kmem_alloc_type = B_FALSE;
3225 
3226         status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
3227             &nxge_desc_dma_attr,
3228             size,
3229             &nxge_dev_desc_dma_acc_attr,
3230             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
3231             tx_dmap);
3232         if (status != NXGE_OK) {
3233                 goto nxge_alloc_tx_cntl_dma_fail1;
3234         }
3235 
3236         *dmap = tx_dmap;
3237         goto nxge_alloc_tx_cntl_dma_exit;
3238 
3239 nxge_alloc_tx_cntl_dma_fail1:
3240         KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t));
3241 
3242 nxge_alloc_tx_cntl_dma_exit:
3243         NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3244             "<== nxge_alloc_tx_cntl_dma status 0x%08x", status));
3245 
3246         return (status);
3247 }
3248 
3249 /*ARGSUSED*/
3250 static void
3251 nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap)
3252 {
3253         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma"));
3254 
3255         if (dmap == 0)
3256                 return;
3257 
3258         nxge_dma_mem_free(dmap);
3259 
3260         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma"));
3261 }
3262 
3263 /*
3264  * nxge_free_tx_mem_pool
3265  *
3266  *      This function frees all of the per-port TDC control data structures.
3267  *      The per-channel (TDC) data structures are freed when the channel
3268  *      is stopped.
3269  *
3270  * Arguments:
3271  *      nxgep
3272  *
3273  * Notes:
3274  *
3275  * Context:
3276  *      Any domain
3277  */
3278 static void
3279 nxge_free_tx_mem_pool(p_nxge_t nxgep)
3280 {
3281         int tdc_max = NXGE_MAX_TDCS;
3282 
3283         NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_tx_mem_pool"));
3284 
3285         if (!nxgep->tx_buf_pool_p || !nxgep->tx_buf_pool_p->buf_allocated) {
3286                 NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
3287                     "<== nxge_free_tx_mem_pool "
3288                     "(null tx buf pool or buf not allocated"));
3289                 return;
3290         }
3291         if (!nxgep->tx_cntl_pool_p || !nxgep->tx_cntl_pool_p->buf_allocated) {
3292                 NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
3293                     "<== nxge_free_tx_mem_pool "
3294                     "(null tx cntl buf pool or cntl buf not allocated"));
3295                 return;
3296         }
3297 
3298         /* 1. Free the mailboxes. */
3299         KMEM_FREE(nxgep->tx_mbox_areas_p->txmbox_areas_p,
3300             sizeof (p_tx_mbox_t) * tdc_max);
3301         KMEM_FREE(nxgep->tx_mbox_areas_p, sizeof (tx_mbox_areas_t));
3302 
3303         nxgep->tx_mbox_areas_p = 0;
3304 
3305         /* 2. Free the transmit ring arrays. */
3306         KMEM_FREE(nxgep->tx_rings->rings,
3307             sizeof (p_tx_ring_t) * tdc_max);
3308         KMEM_FREE(nxgep->tx_rings, sizeof (tx_rings_t));
3309 
3310         nxgep->tx_rings = 0;
3311 
3312         /* 3. Free the completion ring data structures. */
3313         KMEM_FREE(nxgep->tx_cntl_pool_p->dma_buf_pool_p,
3314             sizeof (p_nxge_dma_common_t) * tdc_max);
3315         KMEM_FREE(nxgep->tx_cntl_pool_p, sizeof (nxge_dma_pool_t));
3316 
3317         nxgep->tx_cntl_pool_p = 0;
3318 
3319         /* 4. Free the data ring data structures. */
3320         KMEM_FREE(nxgep->tx_buf_pool_p->num_chunks,
3321             sizeof (uint32_t) * tdc_max);
3322         KMEM_FREE(nxgep->tx_buf_pool_p->dma_buf_pool_p,
3323             sizeof (p_nxge_dma_common_t) * tdc_max);
3324         KMEM_FREE(nxgep->tx_buf_pool_p, sizeof (nxge_dma_pool_t));
3325 
3326         nxgep->tx_buf_pool_p = 0;
3327 
3328         NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_tx_mem_pool"));
3329 }
3330 
3331 /*ARGSUSED*/
3332 static nxge_status_t
3333 nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method,
3334         struct ddi_dma_attr *dma_attrp,
3335         size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags,
3336         p_nxge_dma_common_t dma_p)
3337 {
3338         caddr_t                 kaddrp;
3339         int                     ddi_status = DDI_SUCCESS;
3340         boolean_t               contig_alloc_type;
3341         boolean_t               kmem_alloc_type;
3342 
3343         contig_alloc_type = dma_p->contig_alloc_type;
3344 
3345         if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) {
3346                 /*
3347                  * contig_alloc_type for contiguous memory only allowed
3348                  * for N2/NIU.
3349                  */
3350                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3351                     "nxge_dma_mem_alloc: alloc type not allowed (%d)",
3352                     dma_p->contig_alloc_type));
3353                 return (NXGE_ERROR | NXGE_DDI_FAILED);
3354         }
3355 
3356         dma_p->dma_handle = NULL;
3357         dma_p->acc_handle = NULL;
3358         dma_p->kaddrp = dma_p->last_kaddrp = NULL;
3359         dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL;
3360         ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp,
3361             DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle);
3362         if (ddi_status != DDI_SUCCESS) {
3363                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3364                     "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed."));
3365                 return (NXGE_ERROR | NXGE_DDI_FAILED);
3366         }
3367 
3368         kmem_alloc_type = dma_p->kmem_alloc_type;
3369 
3370         switch (contig_alloc_type) {
3371         case B_FALSE:
3372                 switch (kmem_alloc_type) {
3373                 case B_FALSE:
3374                         ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle,
3375                             length,
3376                             acc_attr_p,
3377                             xfer_flags,
3378                             DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength,
3379                             &dma_p->acc_handle);
3380                         if (ddi_status != DDI_SUCCESS) {
3381                                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3382                                     "nxge_dma_mem_alloc: "
3383                                     "ddi_dma_mem_alloc failed"));
3384                                 ddi_dma_free_handle(&dma_p->dma_handle);
3385                                 dma_p->dma_handle = NULL;
3386                                 return (NXGE_ERROR | NXGE_DDI_FAILED);
3387                         }
3388                         if (dma_p->alength < length) {
3389                                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3390                                     "nxge_dma_mem_alloc:di_dma_mem_alloc "
3391                                     "< length."));
3392                                 ddi_dma_mem_free(&dma_p->acc_handle);
3393                                 ddi_dma_free_handle(&dma_p->dma_handle);
3394                                 dma_p->acc_handle = NULL;
3395                                 dma_p->dma_handle = NULL;
3396                                 return (NXGE_ERROR);
3397                         }
3398 
3399                         ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle,
3400                             NULL,
3401                             kaddrp, dma_p->alength, xfer_flags,
3402                             DDI_DMA_DONTWAIT,
3403                             0, &dma_p->dma_cookie, &dma_p->ncookies);
3404                         if (ddi_status != DDI_DMA_MAPPED) {
3405                                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3406                                     "nxge_dma_mem_alloc: ddi_dma_addr_bind "
3407                                     "failed "
3408                                     "(staus 0x%x ncookies %d.)", ddi_status,
3409                                     dma_p->ncookies));
3410                                 if (dma_p->acc_handle) {
3411                                         ddi_dma_mem_free(&dma_p->acc_handle);
3412                                         dma_p->acc_handle = NULL;
3413                                 }
3414                                 ddi_dma_free_handle(&dma_p->dma_handle);
3415                                 dma_p->dma_handle = NULL;
3416                                 return (NXGE_ERROR | NXGE_DDI_FAILED);
3417                         }
3418 
3419                         if (dma_p->ncookies != 1) {
3420                                 NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3421                                     "nxge_dma_mem_alloc:ddi_dma_addr_bind "
3422                                     "> 1 cookie"
3423                                     "(staus 0x%x ncookies %d.)", ddi_status,
3424                                     dma_p->ncookies));
3425                                 (void) ddi_dma_unbind_handle(dma_p->dma_handle);
3426                                 if (dma_p->acc_handle) {
3427                                         ddi_dma_mem_free(&dma_p->acc_handle);
3428                                         dma_p->acc_handle = NULL;
3429                                 }
3430                                 ddi_dma_free_handle(&dma_p->dma_handle);
3431                                 dma_p->dma_handle = NULL;
3432                                 dma_p->acc_handle = NULL;
3433                                 return (NXGE_ERROR);
3434                         }
3435                         break;
3436 
3437                 case B_TRUE:
3438                         kaddrp = KMEM_ALLOC(length, KM_NOSLEEP);
3439                         if (kaddrp == NULL) {
3440                                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3441                                     "nxge_dma_mem_alloc:ddi_dma_mem_alloc "
3442                                     "kmem alloc failed"));
3443                                 return (NXGE_ERROR);
3444                         }
3445 
3446                         dma_p->alength = length;
3447                         ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle,
3448                             NULL, kaddrp, dma_p->alength, xfer_flags,
3449                             DDI_DMA_DONTWAIT, 0,
3450                             &dma_p->dma_cookie, &dma_p->ncookies);
3451                         if (ddi_status != DDI_DMA_MAPPED) {
3452                                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3453                                     "nxge_dma_mem_alloc:ddi_dma_addr_bind: "
3454                                     "(kmem_alloc) failed kaddrp $%p length %d "
3455                                     "(staus 0x%x (%d) ncookies %d.)",
3456                                     kaddrp, length,
3457                                     ddi_status, ddi_status, dma_p->ncookies));
3458                                 KMEM_FREE(kaddrp, length);
3459                                 dma_p->acc_handle = NULL;
3460                                 ddi_dma_free_handle(&dma_p->dma_handle);
3461                                 dma_p->dma_handle = NULL;
3462                                 dma_p->kaddrp = NULL;
3463                                 return (NXGE_ERROR | NXGE_DDI_FAILED);
3464                         }
3465 
3466                         if (dma_p->ncookies != 1) {
3467                                 NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3468                                     "nxge_dma_mem_alloc:ddi_dma_addr_bind "
3469                                     "(kmem_alloc) > 1 cookie"
3470                                     "(staus 0x%x ncookies %d.)", ddi_status,
3471                                     dma_p->ncookies));
3472                                 (void) ddi_dma_unbind_handle(dma_p->dma_handle);
3473                                 KMEM_FREE(kaddrp, length);
3474                                 ddi_dma_free_handle(&dma_p->dma_handle);
3475                                 dma_p->dma_handle = NULL;
3476                                 dma_p->acc_handle = NULL;
3477                                 dma_p->kaddrp = NULL;
3478                                 return (NXGE_ERROR);
3479                         }
3480 
3481                         dma_p->kaddrp = kaddrp;
3482 
3483                         NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
3484                             "nxge_dma_mem_alloc: kmem_alloc dmap $%p "
3485                             "kaddr $%p alength %d",
3486                             dma_p,
3487                             kaddrp,
3488                             dma_p->alength));
3489                         break;
3490                 }
3491                 break;
3492 
3493 #if     defined(sun4v) && defined(NIU_LP_WORKAROUND)
3494         case B_TRUE:
3495                 kaddrp = (caddr_t)contig_mem_alloc(length);
3496                 if (kaddrp == NULL) {
3497                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3498                             "nxge_dma_mem_alloc:contig_mem_alloc failed."));
3499                         ddi_dma_free_handle(&dma_p->dma_handle);
3500                         return (NXGE_ERROR | NXGE_DDI_FAILED);
3501                 }
3502 
3503                 dma_p->alength = length;
3504                 ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
3505                     kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
3506                     &dma_p->dma_cookie, &dma_p->ncookies);
3507                 if (ddi_status != DDI_DMA_MAPPED) {
3508                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3509                             "nxge_dma_mem_alloc:di_dma_addr_bind failed "
3510                             "(status 0x%x ncookies %d.)", ddi_status,
3511                             dma_p->ncookies));
3512 
3513                         NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3514                             "==> nxge_dma_mem_alloc: (not mapped)"
3515                             "length %lu (0x%x) "
3516                             "free contig kaddrp $%p "
3517                             "va_to_pa $%p",
3518                             length, length,
3519                             kaddrp,
3520                             va_to_pa(kaddrp)));
3521 
3522 
3523                         contig_mem_free((void *)kaddrp, length);
3524                         ddi_dma_free_handle(&dma_p->dma_handle);
3525 
3526                         dma_p->dma_handle = NULL;
3527                         dma_p->acc_handle = NULL;
3528                         dma_p->alength = NULL;
3529                         dma_p->kaddrp = NULL;
3530 
3531                         return (NXGE_ERROR | NXGE_DDI_FAILED);
3532                 }
3533 
3534                 if (dma_p->ncookies != 1 ||
3535                     (dma_p->dma_cookie.dmac_laddress == NULL)) {
3536                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3537                             "nxge_dma_mem_alloc:di_dma_addr_bind > 1 "
3538                             "cookie or "
3539                             "dmac_laddress is NULL $%p size %d "
3540                             " (status 0x%x ncookies %d.)",
3541                             ddi_status,
3542                             dma_p->dma_cookie.dmac_laddress,
3543                             dma_p->dma_cookie.dmac_size,
3544                             dma_p->ncookies));
3545 
3546                         contig_mem_free((void *)kaddrp, length);
3547                         (void) ddi_dma_unbind_handle(dma_p->dma_handle);
3548                         ddi_dma_free_handle(&dma_p->dma_handle);
3549 
3550                         dma_p->alength = 0;
3551                         dma_p->dma_handle = NULL;
3552                         dma_p->acc_handle = NULL;
3553                         dma_p->kaddrp = NULL;
3554 
3555                         return (NXGE_ERROR | NXGE_DDI_FAILED);
3556                 }
3557                 break;
3558 
3559 #else
3560         case B_TRUE:
3561                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3562                     "nxge_dma_mem_alloc: invalid alloc type for !sun4v"));
3563                 return (NXGE_ERROR | NXGE_DDI_FAILED);
3564 #endif
3565         }
3566 
3567         dma_p->kaddrp = kaddrp;
3568         dma_p->last_kaddrp = (unsigned char *)kaddrp +
3569             dma_p->alength - RXBUF_64B_ALIGNED;
3570 #if defined(__i386)
3571         dma_p->ioaddr_pp =
3572             (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress;
3573 #else
3574         dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress;
3575 #endif
3576         dma_p->last_ioaddr_pp =
3577 #if defined(__i386)
3578             (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress +
3579 #else
3580             (unsigned char *)dma_p->dma_cookie.dmac_laddress +
3581 #endif
3582             dma_p->alength - RXBUF_64B_ALIGNED;
3583 
3584         NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle);
3585 
3586 #if     defined(sun4v) && defined(NIU_LP_WORKAROUND)
3587         dma_p->orig_ioaddr_pp =
3588             (unsigned char *)dma_p->dma_cookie.dmac_laddress;
3589         dma_p->orig_alength = length;
3590         dma_p->orig_kaddrp = kaddrp;
3591         dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp);
3592 #endif
3593 
3594         NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: "
3595             "dma buffer allocated: dma_p $%p "
3596             "return dmac_ladress from cookie $%p cookie dmac_size %d "
3597             "dma_p->ioaddr_p $%p "
3598             "dma_p->orig_ioaddr_p $%p "
3599             "orig_vatopa $%p "
3600             "alength %d (0x%x) "
3601             "kaddrp $%p "
3602             "length %d (0x%x)",
3603             dma_p,
3604             dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size,
3605             dma_p->ioaddr_pp,
3606             dma_p->orig_ioaddr_pp,
3607             dma_p->orig_vatopa,
3608             dma_p->alength, dma_p->alength,
3609             kaddrp,
3610             length, length));
3611 
3612         return (NXGE_OK);
3613 }
3614 
3615 static void
3616 nxge_dma_mem_free(p_nxge_dma_common_t dma_p)
3617 {
3618         if (dma_p->dma_handle != NULL) {
3619                 if (dma_p->ncookies) {
3620                         (void) ddi_dma_unbind_handle(dma_p->dma_handle);
3621                         dma_p->ncookies = 0;
3622                 }
3623                 ddi_dma_free_handle(&dma_p->dma_handle);
3624                 dma_p->dma_handle = NULL;
3625         }
3626 
3627         if (dma_p->acc_handle != NULL) {
3628                 ddi_dma_mem_free(&dma_p->acc_handle);
3629                 dma_p->acc_handle = NULL;
3630                 NPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
3631         }
3632 
3633 #if     defined(sun4v) && defined(NIU_LP_WORKAROUND)
3634         if (dma_p->contig_alloc_type &&
3635             dma_p->orig_kaddrp && dma_p->orig_alength) {
3636                 NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: "
3637                     "kaddrp $%p (orig_kaddrp $%p)"
3638                     "mem type %d ",
3639                     "orig_alength %d "
3640                     "alength 0x%x (%d)",
3641                     dma_p->kaddrp,
3642                     dma_p->orig_kaddrp,
3643                     dma_p->contig_alloc_type,
3644                     dma_p->orig_alength,
3645                     dma_p->alength, dma_p->alength));
3646 
3647                 contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength);
3648                 dma_p->orig_alength = NULL;
3649                 dma_p->orig_kaddrp = NULL;
3650                 dma_p->contig_alloc_type = B_FALSE;
3651         }
3652 #endif
3653         dma_p->kaddrp = NULL;
3654         dma_p->alength = NULL;
3655 }
3656 
3657 static void
3658 nxge_dma_free_rx_data_buf(p_nxge_dma_common_t dma_p)
3659 {
3660         uint64_t kaddr;
3661         uint32_t buf_size;
3662 
3663         NXGE_DEBUG_MSG((NULL, DMA_CTL, "==> nxge_dma_free_rx_data_buf"));
3664 
3665         if (dma_p->dma_handle != NULL) {
3666                 if (dma_p->ncookies) {
3667                         (void) ddi_dma_unbind_handle(dma_p->dma_handle);
3668                         dma_p->ncookies = 0;
3669                 }
3670                 ddi_dma_free_handle(&dma_p->dma_handle);
3671                 dma_p->dma_handle = NULL;
3672         }
3673 
3674         if (dma_p->acc_handle != NULL) {
3675                 ddi_dma_mem_free(&dma_p->acc_handle);
3676                 dma_p->acc_handle = NULL;
3677                 NPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
3678         }
3679 
3680         NXGE_DEBUG_MSG((NULL, DMA_CTL,
3681             "==> nxge_dma_free_rx_data_buf: dmap $%p buf_alloc_state %d",
3682             dma_p,
3683             dma_p->buf_alloc_state));
3684 
3685         if (!(dma_p->buf_alloc_state & BUF_ALLOCATED_WAIT_FREE)) {
3686                 NXGE_DEBUG_MSG((NULL, DMA_CTL,
3687                     "<== nxge_dma_free_rx_data_buf: "
3688                     "outstanding data buffers"));
3689                 return;
3690         }
3691 
3692 #if     defined(sun4v) && defined(NIU_LP_WORKAROUND)
3693         if (dma_p->contig_alloc_type &&
3694             dma_p->orig_kaddrp && dma_p->orig_alength) {
3695                 NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_free_rx_data_buf: "
3696                     "kaddrp $%p (orig_kaddrp $%p)"
3697                     "mem type %d ",
3698                     "orig_alength %d "
3699                     "alength 0x%x (%d)",
3700                     dma_p->kaddrp,
3701                     dma_p->orig_kaddrp,
3702                     dma_p->contig_alloc_type,
3703                     dma_p->orig_alength,
3704                     dma_p->alength, dma_p->alength));
3705 
3706                 kaddr = (uint64_t)dma_p->orig_kaddrp;
3707                 buf_size = dma_p->orig_alength;
3708                 nxge_free_buf(CONTIG_MEM_ALLOC, kaddr, buf_size);
3709                 dma_p->orig_alength = NULL;
3710                 dma_p->orig_kaddrp = NULL;
3711                 dma_p->contig_alloc_type = B_FALSE;
3712                 dma_p->kaddrp = NULL;
3713                 dma_p->alength = NULL;
3714                 return;
3715         }
3716 #endif
3717 
3718         if (dma_p->kmem_alloc_type) {
3719                 NXGE_DEBUG_MSG((NULL, DMA_CTL,
3720                     "nxge_dma_free_rx_data_buf: free kmem "
3721                     "kaddrp $%p (orig_kaddrp $%p)"
3722                     "alloc type %d "
3723                     "orig_alength %d "
3724                     "alength 0x%x (%d)",
3725                     dma_p->kaddrp,
3726                     dma_p->orig_kaddrp,
3727                     dma_p->kmem_alloc_type,
3728                     dma_p->orig_alength,
3729                     dma_p->alength, dma_p->alength));
3730 #if defined(__i386)
3731                 kaddr = (uint64_t)(uint32_t)dma_p->kaddrp;
3732 #else
3733                 kaddr = (uint64_t)dma_p->kaddrp;
3734 #endif
3735                 buf_size = dma_p->orig_alength;
3736                 NXGE_DEBUG_MSG((NULL, DMA_CTL,
3737                     "nxge_dma_free_rx_data_buf: free dmap $%p "
3738                     "kaddr $%p buf_size %d",
3739                     dma_p,
3740                     kaddr, buf_size));
3741                 nxge_free_buf(KMEM_ALLOC, kaddr, buf_size);
3742                 dma_p->alength = 0;
3743                 dma_p->orig_alength = 0;
3744                 dma_p->kaddrp = NULL;
3745                 dma_p->kmem_alloc_type = B_FALSE;
3746         }
3747 
3748         NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_dma_free_rx_data_buf"));
3749 }
3750 
3751 /*
3752  *      nxge_m_start() -- start transmitting and receiving.
3753  *
3754  *      This function is called by the MAC layer when the first
3755  *      stream is open to prepare the hardware ready for sending
3756  *      and transmitting packets.
3757  */
3758 static int
3759 nxge_m_start(void *arg)
3760 {
3761         p_nxge_t        nxgep = (p_nxge_t)arg;
3762 
3763         NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start"));
3764 
3765         /*
3766          * Are we already started?
3767          */
3768         if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
3769                 return (0);
3770         }
3771 
3772         if (nxge_peu_reset_enable && !nxgep->nxge_link_poll_timerid) {
3773                 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
3774         }
3775 
3776         /*
3777          * Make sure RX MAC is disabled while we initialize.
3778          */
3779         if (!isLDOMguest(nxgep)) {
3780                 (void) nxge_rx_mac_disable(nxgep);
3781         }
3782 
3783         /*
3784          * Grab the global lock.
3785          */
3786         MUTEX_ENTER(nxgep->genlock);
3787 
3788         /*
3789          * Initialize the driver and hardware.
3790          */
3791         if (nxge_init(nxgep) != NXGE_OK) {
3792                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3793                     "<== nxge_m_start: initialization failed"));
3794                 MUTEX_EXIT(nxgep->genlock);
3795                 return (EIO);
3796         }
3797 
3798         /*
3799          * Start timer to check the system error and tx hangs
3800          */
3801         if (!isLDOMguest(nxgep))
3802                 nxgep->nxge_timerid = nxge_start_timer(nxgep,
3803                     nxge_check_hw_state, NXGE_CHECK_TIMER);
3804 #if defined(sun4v)
3805         else
3806                 nxge_hio_start_timer(nxgep);
3807 #endif
3808 
3809         nxgep->link_notify = B_TRUE;
3810         nxgep->link_check_count = 0;
3811         nxgep->nxge_mac_state = NXGE_MAC_STARTED;
3812 
3813         /*
3814          * Let the global lock go, since we are intialized.
3815          */
3816         MUTEX_EXIT(nxgep->genlock);
3817 
3818         /*
3819          * Let the MAC start receiving packets, now that
3820          * we are initialized.
3821          */
3822         if (!isLDOMguest(nxgep)) {
3823                 if (nxge_rx_mac_enable(nxgep) != NXGE_OK) {
3824                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3825                             "<== nxge_m_start: enable of RX mac failed"));
3826                         return (EIO);
3827                 }
3828 
3829                 /*
3830                  * Enable hardware interrupts.
3831                  */
3832                 nxge_intr_hw_enable(nxgep);
3833         }
3834 #if defined(sun4v)
3835         else {
3836                 /*
3837                  * In guest domain we enable RDCs and their interrupts as
3838                  * the last step.
3839                  */
3840                 if (nxge_hio_rdc_enable(nxgep) != NXGE_OK) {
3841                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3842                             "<== nxge_m_start: enable of RDCs failed"));
3843                         return (EIO);
3844                 }
3845 
3846                 if (nxge_hio_rdc_intr_arm(nxgep, B_TRUE) != NXGE_OK) {
3847                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3848                             "<== nxge_m_start: intrs enable for RDCs failed"));
3849                         return (EIO);
3850                 }
3851         }
3852 #endif
3853         NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start"));
3854         return (0);
3855 }
3856 
3857 static boolean_t
3858 nxge_check_groups_stopped(p_nxge_t nxgep)
3859 {
3860         int     i;
3861 
3862         for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) {
3863                 if (nxgep->rx_hio_groups[i].started)
3864                         return (B_FALSE);
3865         }
3866 
3867         return (B_TRUE);
3868 }
3869 
3870 /*
3871  *      nxge_m_stop(): stop transmitting and receiving.
3872  */
3873 static void
3874 nxge_m_stop(void *arg)
3875 {
3876         p_nxge_t        nxgep = (p_nxge_t)arg;
3877         boolean_t       groups_stopped;
3878 
3879         NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop"));
3880 
3881         /*
3882          * Are the groups stopped?
3883          */
3884         groups_stopped = nxge_check_groups_stopped(nxgep);
3885         ASSERT(groups_stopped == B_TRUE);
3886         if (!groups_stopped) {
3887                 cmn_err(CE_WARN, "nxge(%d): groups are not stopped!\n",
3888                     nxgep->instance);
3889                 return;
3890         }
3891 
3892         if (!isLDOMguest(nxgep)) {
3893                 /*
3894                  * Disable the RX mac.
3895                  */
3896                 (void) nxge_rx_mac_disable(nxgep);
3897 
3898                 /*
3899                  * Wait for the IPP to drain.
3900                  */
3901                 (void) nxge_ipp_drain(nxgep);
3902 
3903                 /*
3904                  * Disable hardware interrupts.
3905                  */
3906                 nxge_intr_hw_disable(nxgep);
3907         }
3908 #if defined(sun4v)
3909         else {
3910                 (void) nxge_hio_rdc_intr_arm(nxgep, B_FALSE);
3911         }
3912 #endif
3913 
3914         /*
3915          * Grab the global lock.
3916          */
3917         MUTEX_ENTER(nxgep->genlock);
3918 
3919         nxgep->nxge_mac_state = NXGE_MAC_STOPPING;
3920         if (nxgep->nxge_timerid) {
3921                 nxge_stop_timer(nxgep, nxgep->nxge_timerid);
3922                 nxgep->nxge_timerid = 0;
3923         }
3924 
3925         /*
3926          * Clean up.
3927          */
3928         nxge_uninit(nxgep);
3929 
3930         nxgep->nxge_mac_state = NXGE_MAC_STOPPED;
3931 
3932         /*
3933          * Let go of the global lock.
3934          */
3935         MUTEX_EXIT(nxgep->genlock);
3936         NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop"));
3937 }
3938 
3939 static int
3940 nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
3941 {
3942         p_nxge_t        nxgep = (p_nxge_t)arg;
3943         struct          ether_addr addrp;
3944 
3945         NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3946             "==> nxge_m_multicst: add %d", add));
3947 
3948         bcopy(mca, (uint8_t *)&addrp, ETHERADDRL);
3949         if (add) {
3950                 if (nxge_add_mcast_addr(nxgep, &addrp)) {
3951                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3952                             "<== nxge_m_multicst: add multicast failed"));
3953                         return (EINVAL);
3954                 }
3955         } else {
3956                 if (nxge_del_mcast_addr(nxgep, &addrp)) {
3957                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3958                             "<== nxge_m_multicst: del multicast failed"));
3959                         return (EINVAL);
3960                 }
3961         }
3962 
3963         NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst"));
3964 
3965         return (0);
3966 }
3967 
3968 static int
3969 nxge_m_promisc(void *arg, boolean_t on)
3970 {
3971         p_nxge_t        nxgep = (p_nxge_t)arg;
3972 
3973         NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3974             "==> nxge_m_promisc: on %d", on));
3975 
3976         if (nxge_set_promisc(nxgep, on)) {
3977                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3978                     "<== nxge_m_promisc: set promisc failed"));
3979                 return (EINVAL);
3980         }
3981 
3982         NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3983             "<== nxge_m_promisc: on %d", on));
3984 
3985         return (0);
3986 }
3987 
3988 static void
3989 nxge_m_ioctl(void *arg,  queue_t *wq, mblk_t *mp)
3990 {
3991         p_nxge_t        nxgep = (p_nxge_t)arg;
3992         struct          iocblk *iocp;
3993         boolean_t       need_privilege;
3994         int             err;
3995         int             cmd;
3996 
3997         NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl"));
3998 
3999         iocp = (struct iocblk *)mp->b_rptr;
4000         iocp->ioc_error = 0;
4001         need_privilege = B_TRUE;
4002         cmd = iocp->ioc_cmd;
4003         NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd));
4004         switch (cmd) {
4005         default:
4006                 miocnak(wq, mp, 0, EINVAL);
4007                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid"));
4008                 return;
4009 
4010         case LB_GET_INFO_SIZE:
4011         case LB_GET_INFO:
4012         case LB_GET_MODE:
4013                 need_privilege = B_FALSE;
4014                 break;
4015         case LB_SET_MODE:
4016                 break;
4017 
4018 
4019         case NXGE_GET_MII:
4020         case NXGE_PUT_MII:
4021         case NXGE_GET64:
4022         case NXGE_PUT64:
4023         case NXGE_GET_TX_RING_SZ:
4024         case NXGE_GET_TX_DESC:
4025         case NXGE_TX_SIDE_RESET:
4026         case NXGE_RX_SIDE_RESET:
4027         case NXGE_GLOBAL_RESET:
4028         case NXGE_RESET_MAC:
4029         case NXGE_TX_REGS_DUMP:
4030         case NXGE_RX_REGS_DUMP:
4031         case NXGE_INT_REGS_DUMP:
4032         case NXGE_VIR_INT_REGS_DUMP:
4033         case NXGE_PUT_TCAM:
4034         case NXGE_GET_TCAM:
4035         case NXGE_RTRACE:
4036         case NXGE_RDUMP:
4037         case NXGE_RX_CLASS:
4038         case NXGE_RX_HASH:
4039 
4040                 need_privilege = B_FALSE;
4041                 break;
4042         case NXGE_INJECT_ERR:
4043                 cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n");
4044                 nxge_err_inject(nxgep, wq, mp);
4045                 break;
4046         }
4047 
4048         if (need_privilege) {
4049                 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
4050                 if (err != 0) {
4051                         miocnak(wq, mp, 0, err);
4052                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4053                             "<== nxge_m_ioctl: no priv"));
4054                         return;
4055                 }
4056         }
4057 
4058         switch (cmd) {
4059 
4060         case LB_GET_MODE:
4061         case LB_SET_MODE:
4062         case LB_GET_INFO_SIZE:
4063         case LB_GET_INFO:
4064                 nxge_loopback_ioctl(nxgep, wq, mp, iocp);
4065                 break;
4066 
4067         case NXGE_GET_MII:
4068         case NXGE_PUT_MII:
4069         case NXGE_PUT_TCAM:
4070         case NXGE_GET_TCAM:
4071         case NXGE_GET64:
4072         case NXGE_PUT64:
4073         case NXGE_GET_TX_RING_SZ:
4074         case NXGE_GET_TX_DESC:
4075         case NXGE_TX_SIDE_RESET:
4076         case NXGE_RX_SIDE_RESET:
4077         case NXGE_GLOBAL_RESET:
4078         case NXGE_RESET_MAC:
4079         case NXGE_TX_REGS_DUMP:
4080         case NXGE_RX_REGS_DUMP:
4081         case NXGE_INT_REGS_DUMP:
4082         case NXGE_VIR_INT_REGS_DUMP:
4083                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4084                     "==> nxge_m_ioctl: cmd 0x%x", cmd));
4085                 nxge_hw_ioctl(nxgep, wq, mp, iocp);
4086                 break;
4087         case NXGE_RX_CLASS:
4088                 if (nxge_rxclass_ioctl(nxgep, wq, mp->b_cont) < 0)
4089                         miocnak(wq, mp, 0, EINVAL);
4090                 else
4091                         miocack(wq, mp, sizeof (rx_class_cfg_t), 0);
4092                 break;
4093         case NXGE_RX_HASH:
4094 
4095                 if (nxge_rxhash_ioctl(nxgep, wq, mp->b_cont) < 0)
4096                         miocnak(wq, mp, 0, EINVAL);
4097                 else
4098                         miocack(wq, mp, sizeof (cfg_cmd_t), 0);
4099                 break;
4100         }
4101 
4102         NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl"));
4103 }
4104 
4105 extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count);
4106 
4107 void
4108 nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, boolean_t factory)
4109 {
4110         p_nxge_mmac_stats_t mmac_stats;
4111         int i;
4112         nxge_mmac_t *mmac_info;
4113 
4114         mmac_info = &nxgep->nxge_mmac_info;
4115 
4116         mmac_stats = &nxgep->statsp->mmac_stats;
4117         mmac_stats->mmac_max_cnt = mmac_info->num_mmac;
4118         mmac_stats->mmac_avail_cnt = mmac_info->naddrfree;
4119 
4120         for (i = 0; i < ETHERADDRL; i++) {
4121                 if (factory) {
4122                         mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i]
4123                             = mmac_info->factory_mac_pool[slot][
4124                             (ETHERADDRL-1) - i];
4125                 } else {
4126                         mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i]
4127                             = mmac_info->mac_pool[slot].addr[
4128                             (ETHERADDRL - 1) - i];
4129                 }
4130         }
4131 }
4132 
4133 /*
4134  * nxge_altmac_set() -- Set an alternate MAC address
4135  */
4136 static int
4137 nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, int slot,
4138         int rdctbl, boolean_t usetbl)
4139 {
4140         uint8_t addrn;
4141         uint8_t portn;
4142         npi_mac_addr_t altmac;
4143         hostinfo_t mac_rdc;
4144         p_nxge_class_pt_cfg_t clscfgp;
4145 
4146 
4147         altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff);
4148         altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff);
4149         altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff);
4150 
4151         portn = nxgep->mac.portnum;
4152         addrn = (uint8_t)slot - 1;
4153 
4154         if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET,
4155             nxgep->function_num, addrn, &altmac) != NPI_SUCCESS)
4156                 return (EIO);
4157 
4158         /*
4159          * Set the rdc table number for the host info entry
4160          * for this mac address slot.
4161          */
4162         clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
4163         mac_rdc.value = 0;
4164         if (usetbl)
4165                 mac_rdc.bits.w0.rdc_tbl_num = rdctbl;
4166         else
4167                 mac_rdc.bits.w0.rdc_tbl_num =
4168                     clscfgp->mac_host_info[addrn].rdctbl;
4169         mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr;
4170 
4171         if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET,
4172             nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) {
4173                 return (EIO);
4174         }
4175 
4176         /*
4177          * Enable comparison with the alternate MAC address.
4178          * While the first alternate addr is enabled by bit 1 of register
4179          * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register
4180          * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn
4181          * accordingly before calling npi_mac_altaddr_entry.
4182          */
4183         if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1)
4184                 addrn = (uint8_t)slot - 1;
4185         else
4186                 addrn = (uint8_t)slot;
4187 
4188         if (npi_mac_altaddr_enable(nxgep->npi_handle,
4189             nxgep->function_num, addrn) != NPI_SUCCESS) {
4190                 return (EIO);
4191         }
4192 
4193         return (0);
4194 }
4195 
4196 /*
4197  * nxeg_m_mmac_add_g() - find an unused address slot, set the address
4198  * value to the one specified, enable the port to start filtering on
4199  * the new MAC address.  Returns 0 on success.
4200  */
4201 int
4202 nxge_m_mmac_add_g(void *arg, const uint8_t *maddr, int rdctbl,
4203         boolean_t usetbl)
4204 {
4205         p_nxge_t nxgep = arg;
4206         int slot;
4207         nxge_mmac_t *mmac_info;
4208         int err;
4209         nxge_status_t status;
4210 
4211         mutex_enter(nxgep->genlock);
4212 
4213         /*
4214          * Make sure that nxge is initialized, if _start() has
4215          * not been called.
4216          */
4217         if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
4218                 status = nxge_init(nxgep);
4219                 if (status != NXGE_OK) {
4220                         mutex_exit(nxgep->genlock);
4221                         return (ENXIO);
4222                 }
4223         }
4224 
4225         mmac_info = &nxgep->nxge_mmac_info;
4226         if (mmac_info->naddrfree == 0) {
4227                 mutex_exit(nxgep->genlock);
4228                 return (ENOSPC);
4229         }
4230 
4231         /*
4232          *      Search for the first available slot. Because naddrfree
4233          * is not zero, we are guaranteed to find one.
4234          *      Each of the first two ports of Neptune has 16 alternate
4235          * MAC slots but only the first 7 (of 15) slots have assigned factory
4236          * MAC addresses. We first search among the slots without bundled
4237          * factory MACs. If we fail to find one in that range, then we
4238          * search the slots with bundled factory MACs.  A factory MAC
4239          * will be wasted while the slot is used with a user MAC address.
4240          * But the slot could be used by factory MAC again after calling
4241          * nxge_m_mmac_remove and nxge_m_mmac_reserve.
4242          */
4243         for (slot = 0; slot <= mmac_info->num_mmac; slot++) {
4244                 if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
4245                         break;
4246         }
4247 
4248         ASSERT(slot <= mmac_info->num_mmac);
4249 
4250         if ((err = nxge_altmac_set(nxgep, (uint8_t *)maddr, slot, rdctbl,
4251             usetbl)) != 0) {
4252                 mutex_exit(nxgep->genlock);
4253                 return (err);
4254         }
4255 
4256         bcopy(maddr, mmac_info->mac_pool[slot].addr, ETHERADDRL);
4257         mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED;
4258         mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR;
4259         mmac_info->naddrfree--;
4260         nxge_mmac_kstat_update(nxgep, slot, B_FALSE);
4261 
4262         mutex_exit(nxgep->genlock);
4263         return (0);
4264 }
4265 
4266 /*
4267  * Remove the specified mac address and update the HW not to filter
4268  * the mac address anymore.
4269  */
4270 int
4271 nxge_m_mmac_remove(void *arg, int slot)
4272 {
4273         p_nxge_t nxgep = arg;
4274         nxge_mmac_t *mmac_info;
4275         uint8_t addrn;
4276         uint8_t portn;
4277         int err = 0;
4278         nxge_status_t status;
4279 
4280         mutex_enter(nxgep->genlock);
4281 
4282         /*
4283          * Make sure that nxge is initialized, if _start() has
4284          * not been called.
4285          */
4286         if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
4287                 status = nxge_init(nxgep);
4288                 if (status != NXGE_OK) {
4289                         mutex_exit(nxgep->genlock);
4290                         return (ENXIO);
4291                 }
4292         }
4293 
4294         mmac_info = &nxgep->nxge_mmac_info;
4295         if (slot < 1 || slot > mmac_info->num_mmac) {
4296                 mutex_exit(nxgep->genlock);
4297                 return (EINVAL);
4298         }
4299 
4300         portn = nxgep->mac.portnum;
4301         if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1)
4302                 addrn = (uint8_t)slot - 1;
4303         else
4304                 addrn = (uint8_t)slot;
4305 
4306         if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
4307                 if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn)
4308                     == NPI_SUCCESS) {
4309                         mmac_info->naddrfree++;
4310                         mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED;
4311                         /*
4312                          * Regardless if the MAC we just stopped filtering
4313                          * is a user addr or a facory addr, we must set
4314                          * the MMAC_VENDOR_ADDR flag if this slot has an
4315                          * associated factory MAC to indicate that a factory
4316                          * MAC is available.
4317                          */
4318                         if (slot <= mmac_info->num_factory_mmac) {
4319                                 mmac_info->mac_pool[slot].flags
4320                                     |= MMAC_VENDOR_ADDR;
4321                         }
4322                         /*
4323                          * Clear mac_pool[slot].addr so that kstat shows 0
4324                          * alternate MAC address if the slot is not used.
4325                          * (But nxge_m_mmac_get returns the factory MAC even
4326                          * when the slot is not used!)
4327                          */
4328                         bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL);
4329                         nxge_mmac_kstat_update(nxgep, slot, B_FALSE);
4330                 } else {
4331                         err = EIO;
4332                 }
4333         } else {
4334                 err = EINVAL;
4335         }
4336 
4337         mutex_exit(nxgep->genlock);
4338         return (err);
4339 }
4340 
4341 /*
4342  * The callback to query all the factory addresses. naddr must be the same as
4343  * the number of factory addresses (returned by MAC_CAPAB_MULTIFACTADDR), and
4344  * mcm_addr is the space allocated for keep all the addresses, whose size is
4345  * naddr * MAXMACADDRLEN.
4346  */
4347 static void
4348 nxge_m_getfactaddr(void *arg, uint_t naddr, uint8_t *addr)
4349 {
4350         nxge_t          *nxgep = arg;
4351         nxge_mmac_t     *mmac_info;
4352         int             i;
4353 
4354         mutex_enter(nxgep->genlock);
4355 
4356         mmac_info = &nxgep->nxge_mmac_info;
4357         ASSERT(naddr == mmac_info->num_factory_mmac);
4358 
4359         for (i = 0; i < naddr; i++) {
4360                 bcopy(mmac_info->factory_mac_pool[i + 1],
4361                     addr + i * MAXMACADDRLEN, ETHERADDRL);
4362         }
4363 
4364         mutex_exit(nxgep->genlock);
4365 }
4366 
4367 
4368 static boolean_t
4369 nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
4370 {
4371         nxge_t *nxgep = arg;
4372         uint32_t *txflags = cap_data;
4373 
4374         switch (cap) {
4375         case MAC_CAPAB_HCKSUM:
4376                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4377                     "==> nxge_m_getcapab: checksum %d", nxge_cksum_offload));
4378                 if (nxge_cksum_offload <= 1) {
4379                         *txflags = HCKSUM_INET_PARTIAL;
4380                 }
4381                 break;
4382 
4383         case MAC_CAPAB_MULTIFACTADDR: {
4384                 mac_capab_multifactaddr_t       *mfacp = cap_data;
4385 
4386                 if (!isLDOMguest(nxgep)) {
4387                         mutex_enter(nxgep->genlock);
4388                         mfacp->mcm_naddr =
4389                             nxgep->nxge_mmac_info.num_factory_mmac;
4390                         mfacp->mcm_getaddr = nxge_m_getfactaddr;
4391                         mutex_exit(nxgep->genlock);
4392                 }
4393                 break;
4394         }
4395 
4396         case MAC_CAPAB_LSO: {
4397                 mac_capab_lso_t *cap_lso = cap_data;
4398 
4399                 if (nxgep->soft_lso_enable) {
4400                         if (nxge_cksum_offload <= 1) {
4401                                 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
4402                                 if (nxge_lso_max > NXGE_LSO_MAXLEN) {
4403                                         nxge_lso_max = NXGE_LSO_MAXLEN;
4404                                 }
4405                                 cap_lso->lso_basic_tcp_ipv4.lso_max =
4406                                     nxge_lso_max;
4407                         }
4408                         break;
4409                 } else {
4410                         return (B_FALSE);
4411                 }
4412         }
4413 
4414         case MAC_CAPAB_RINGS: {
4415                 mac_capab_rings_t       *cap_rings = cap_data;
4416                 p_nxge_hw_pt_cfg_t      p_cfgp = &nxgep->pt_config.hw_config;
4417 
4418                 mutex_enter(nxgep->genlock);
4419                 if (cap_rings->mr_type == MAC_RING_TYPE_RX) {
4420                         if (isLDOMguest(nxgep))  {
4421                                 cap_rings->mr_group_type =
4422                                     MAC_GROUP_TYPE_STATIC;
4423                                 cap_rings->mr_rnum =
4424                                     NXGE_HIO_SHARE_MAX_CHANNELS;
4425                                 cap_rings->mr_rget = nxge_fill_ring;
4426                                 cap_rings->mr_gnum = 1;
4427                                 cap_rings->mr_gget = nxge_hio_group_get;
4428                                 cap_rings->mr_gaddring = NULL;
4429                                 cap_rings->mr_gremring = NULL;
4430                         } else {
4431                                 /*
4432                                  * Service Domain.
4433                                  */
4434                                 cap_rings->mr_group_type =
4435                                     MAC_GROUP_TYPE_DYNAMIC;
4436                                 cap_rings->mr_rnum = p_cfgp->max_rdcs;
4437                                 cap_rings->mr_rget = nxge_fill_ring;
4438                                 cap_rings->mr_gnum = p_cfgp->max_rdc_grpids;
4439                                 cap_rings->mr_gget = nxge_hio_group_get;
4440                                 cap_rings->mr_gaddring = nxge_group_add_ring;
4441                                 cap_rings->mr_gremring = nxge_group_rem_ring;
4442                         }
4443 
4444                         NXGE_DEBUG_MSG((nxgep, RX_CTL,
4445                             "==> nxge_m_getcapab: rx nrings[%d] ngroups[%d]",
4446                             p_cfgp->max_rdcs, p_cfgp->max_rdc_grpids));
4447                 } else {
4448                         /*
4449                          * TX Rings.
4450                          */
4451                         if (isLDOMguest(nxgep)) {
4452                                 cap_rings->mr_group_type =
4453                                     MAC_GROUP_TYPE_STATIC;
4454                                 cap_rings->mr_rnum =
4455                                     NXGE_HIO_SHARE_MAX_CHANNELS;
4456                                 cap_rings->mr_rget = nxge_fill_ring;
4457                                 cap_rings->mr_gnum = 0;
4458                                 cap_rings->mr_gget = NULL;
4459                                 cap_rings->mr_gaddring = NULL;
4460                                 cap_rings->mr_gremring = NULL;
4461                         } else {
4462                                 /*
4463                                  * Service Domain.
4464                                  */
4465                                 cap_rings->mr_group_type =
4466                                     MAC_GROUP_TYPE_DYNAMIC;
4467                                 cap_rings->mr_rnum = p_cfgp->tdc.count;
4468                                 cap_rings->mr_rget = nxge_fill_ring;
4469 
4470                                 /*
4471                                  * Share capable.
4472                                  *
4473                                  * Do not report the default group: hence -1
4474                                  */
4475                                 cap_rings->mr_gnum =
4476                                     NXGE_MAX_TDC_GROUPS / nxgep->nports - 1;
4477                                 cap_rings->mr_gget = nxge_hio_group_get;
4478                                 cap_rings->mr_gaddring = nxge_group_add_ring;
4479                                 cap_rings->mr_gremring = nxge_group_rem_ring;
4480                         }
4481 
4482                         NXGE_DEBUG_MSG((nxgep, TX_CTL,
4483                             "==> nxge_m_getcapab: tx rings # of rings %d",
4484                             p_cfgp->tdc.count));
4485                 }
4486                 mutex_exit(nxgep->genlock);
4487                 break;
4488         }
4489 
4490 #if defined(sun4v)
4491         case MAC_CAPAB_SHARES: {
4492                 mac_capab_share_t *mshares = (mac_capab_share_t *)cap_data;
4493 
4494                 /*
4495                  * Only the service domain driver responds to
4496                  * this capability request.
4497                  */
4498                 mutex_enter(nxgep->genlock);
4499                 if (isLDOMservice(nxgep)) {
4500                         mshares->ms_snum = 3;
4501                         mshares->ms_handle = (void *)nxgep;
4502                         mshares->ms_salloc = nxge_hio_share_alloc;
4503                         mshares->ms_sfree = nxge_hio_share_free;
4504                         mshares->ms_sadd = nxge_hio_share_add_group;
4505                         mshares->ms_sremove = nxge_hio_share_rem_group;
4506                         mshares->ms_squery = nxge_hio_share_query;
4507                         mshares->ms_sbind = nxge_hio_share_bind;
4508                         mshares->ms_sunbind = nxge_hio_share_unbind;
4509                         mutex_exit(nxgep->genlock);
4510                 } else {
4511                         mutex_exit(nxgep->genlock);
4512                         return (B_FALSE);
4513                 }
4514                 break;
4515         }
4516 #endif
4517         default:
4518                 return (B_FALSE);
4519         }
4520         return (B_TRUE);
4521 }
4522 
4523 static boolean_t
4524 nxge_param_locked(mac_prop_id_t pr_num)
4525 {
4526         /*
4527          * All adv_* parameters are locked (read-only) while
4528          * the device is in any sort of loopback mode ...
4529          */
4530         switch (pr_num) {
4531                 case MAC_PROP_ADV_1000FDX_CAP:
4532                 case MAC_PROP_EN_1000FDX_CAP:
4533                 case MAC_PROP_ADV_1000HDX_CAP:
4534                 case MAC_PROP_EN_1000HDX_CAP:
4535                 case MAC_PROP_ADV_100FDX_CAP:
4536                 case MAC_PROP_EN_100FDX_CAP:
4537                 case MAC_PROP_ADV_100HDX_CAP:
4538                 case MAC_PROP_EN_100HDX_CAP:
4539                 case MAC_PROP_ADV_10FDX_CAP:
4540                 case MAC_PROP_EN_10FDX_CAP:
4541                 case MAC_PROP_ADV_10HDX_CAP:
4542                 case MAC_PROP_EN_10HDX_CAP:
4543                 case MAC_PROP_AUTONEG:
4544                 case MAC_PROP_FLOWCTRL:
4545                         return (B_TRUE);
4546         }
4547         return (B_FALSE);
4548 }
4549 
4550 /*
4551  * callback functions for set/get of properties
4552  */
4553 static int
4554 nxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
4555     uint_t pr_valsize, const void *pr_val)
4556 {
4557         nxge_t          *nxgep = barg;
4558         p_nxge_param_t  param_arr = nxgep->param_arr;
4559         p_nxge_stats_t  statsp = nxgep->statsp;
4560         int             err = 0;
4561 
4562         NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_setprop"));
4563 
4564         mutex_enter(nxgep->genlock);
4565         if (statsp->port_stats.lb_mode != nxge_lb_normal &&
4566             nxge_param_locked(pr_num)) {
4567                 /*
4568                  * All adv_* parameters are locked (read-only)
4569                  * while the device is in any sort of loopback mode.
4570                  */
4571                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4572                     "==> nxge_m_setprop: loopback mode: read only"));
4573                 mutex_exit(nxgep->genlock);
4574                 return (EBUSY);
4575         }
4576 
4577         switch (pr_num) {
4578         case MAC_PROP_EN_1000FDX_CAP:
4579                 nxgep->param_en_1000fdx =
4580                     param_arr[param_anar_1000fdx].value = *(uint8_t *)pr_val;
4581                 goto reprogram;
4582 
4583         case MAC_PROP_EN_100FDX_CAP:
4584                 nxgep->param_en_100fdx =
4585                     param_arr[param_anar_100fdx].value = *(uint8_t *)pr_val;
4586                 goto reprogram;
4587 
4588         case MAC_PROP_EN_10FDX_CAP:
4589                 nxgep->param_en_10fdx =
4590                     param_arr[param_anar_10fdx].value = *(uint8_t *)pr_val;
4591                 goto reprogram;
4592 
4593         case MAC_PROP_AUTONEG:
4594                 param_arr[param_autoneg].value = *(uint8_t *)pr_val;
4595                 goto reprogram;
4596 
4597         case MAC_PROP_MTU: {
4598                 uint32_t cur_mtu, new_mtu, old_framesize;
4599 
4600                 cur_mtu = nxgep->mac.default_mtu;
4601                 ASSERT(pr_valsize >= sizeof (new_mtu));
4602                 bcopy(pr_val, &new_mtu, sizeof (new_mtu));
4603 
4604                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4605                     "==> nxge_m_setprop: set MTU: %d is_jumbo %d",
4606                     new_mtu, nxgep->mac.is_jumbo));
4607 
4608                 if (new_mtu == cur_mtu) {
4609                         err = 0;
4610                         break;
4611                 }
4612 
4613                 if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
4614                         err = EBUSY;
4615                         break;
4616                 }
4617 
4618                 if ((new_mtu < NXGE_DEFAULT_MTU) ||
4619                     (new_mtu > NXGE_MAXIMUM_MTU)) {
4620                         err = EINVAL;
4621                         break;
4622                 }
4623 
4624                 old_framesize = (uint32_t)nxgep->mac.maxframesize;
4625                 nxgep->mac.maxframesize = (uint16_t)
4626                     (new_mtu + NXGE_EHEADER_VLAN_CRC);
4627                 if (nxge_mac_set_framesize(nxgep)) {
4628                         nxgep->mac.maxframesize =
4629                             (uint16_t)old_framesize;
4630                         err = EINVAL;
4631                         break;
4632                 }
4633 
4634                 nxgep->mac.default_mtu = new_mtu;
4635                 nxgep->mac.is_jumbo = (new_mtu > NXGE_DEFAULT_MTU);
4636 
4637                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4638                     "==> nxge_m_setprop: set MTU: %d maxframe %d",
4639                     new_mtu, nxgep->mac.maxframesize));
4640                 break;
4641         }
4642 
4643         case MAC_PROP_FLOWCTRL: {
4644                 link_flowctrl_t fl;
4645 
4646                 ASSERT(pr_valsize >= sizeof (fl));
4647                 bcopy(pr_val, &fl, sizeof (fl));
4648 
4649                 switch (fl) {
4650                 case LINK_FLOWCTRL_NONE:
4651                         param_arr[param_anar_pause].value = 0;
4652                         break;
4653 
4654                 case LINK_FLOWCTRL_RX:
4655                         param_arr[param_anar_pause].value = 1;
4656                         break;
4657 
4658                 case LINK_FLOWCTRL_TX:
4659                 case LINK_FLOWCTRL_BI:
4660                         err = EINVAL;
4661                         break;
4662                 default:
4663                         err = EINVAL;
4664                         break;
4665                 }
4666 reprogram:
4667                 if ((err == 0) && !isLDOMguest(nxgep)) {
4668                         if (!nxge_param_link_update(nxgep)) {
4669                                 err = EINVAL;
4670                         }
4671                 } else {
4672                         err = EINVAL;
4673                 }
4674                 break;
4675         }
4676 
4677         case MAC_PROP_PRIVATE:
4678                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4679                     "==> nxge_m_setprop: private property"));
4680                 err = nxge_set_priv_prop(nxgep, pr_name, pr_valsize, pr_val);
4681                 break;
4682 
4683         default:
4684                 err = ENOTSUP;
4685                 break;
4686         }
4687 
4688         mutex_exit(nxgep->genlock);
4689 
4690         NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4691             "<== nxge_m_setprop (return %d)", err));
4692         return (err);
4693 }
4694 
4695 static int
4696 nxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
4697     uint_t pr_valsize, void *pr_val)
4698 {
4699         nxge_t          *nxgep = barg;
4700         p_nxge_param_t  param_arr = nxgep->param_arr;
4701         p_nxge_stats_t  statsp = nxgep->statsp;
4702 
4703         NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4704             "==> nxge_m_getprop: pr_num %d", pr_num));
4705 
4706         switch (pr_num) {
4707         case MAC_PROP_DUPLEX:
4708                 *(uint8_t *)pr_val = statsp->mac_stats.link_duplex;
4709                 break;
4710 
4711         case MAC_PROP_SPEED: {
4712                 uint64_t val = statsp->mac_stats.link_speed * 1000000ull;
4713 
4714                 ASSERT(pr_valsize >= sizeof (val));
4715                 bcopy(&val, pr_val, sizeof (val));
4716                 break;
4717         }
4718 
4719         case MAC_PROP_STATUS: {
4720                 link_state_t state = statsp->mac_stats.link_up ?
4721                     LINK_STATE_UP : LINK_STATE_DOWN;
4722 
4723                 ASSERT(pr_valsize >= sizeof (state));
4724                 bcopy(&state, pr_val, sizeof (state));
4725                 break;
4726         }
4727 
4728         case MAC_PROP_AUTONEG:
4729                 *(uint8_t *)pr_val = param_arr[param_autoneg].value;
4730                 break;
4731 
4732         case MAC_PROP_FLOWCTRL: {
4733                 link_flowctrl_t fl = param_arr[param_anar_pause].value != 0 ?
4734                     LINK_FLOWCTRL_RX : LINK_FLOWCTRL_NONE;
4735 
4736                 ASSERT(pr_valsize >= sizeof (fl));
4737                 bcopy(&fl, pr_val, sizeof (fl));
4738                 break;
4739         }
4740 
4741         case MAC_PROP_ADV_1000FDX_CAP:
4742                 *(uint8_t *)pr_val = param_arr[param_anar_1000fdx].value;
4743                 break;
4744 
4745         case MAC_PROP_EN_1000FDX_CAP:
4746                 *(uint8_t *)pr_val = nxgep->param_en_1000fdx;
4747                 break;
4748 
4749         case MAC_PROP_ADV_100FDX_CAP:
4750                 *(uint8_t *)pr_val = param_arr[param_anar_100fdx].value;
4751                 break;
4752 
4753         case MAC_PROP_EN_100FDX_CAP:
4754                 *(uint8_t *)pr_val = nxgep->param_en_100fdx;
4755                 break;
4756 
4757         case MAC_PROP_ADV_10FDX_CAP:
4758                 *(uint8_t *)pr_val = param_arr[param_anar_10fdx].value;
4759                 break;
4760 
4761         case MAC_PROP_EN_10FDX_CAP:
4762                 *(uint8_t *)pr_val = nxgep->param_en_10fdx;
4763                 break;
4764 
4765         case MAC_PROP_PRIVATE:
4766                 return (nxge_get_priv_prop(nxgep, pr_name, pr_valsize,
4767                     pr_val));
4768 
4769         default:
4770                 return (ENOTSUP);
4771         }
4772 
4773         return (0);
4774 }
4775 
4776 static void
4777 nxge_m_propinfo(void *barg, const char *pr_name, mac_prop_id_t pr_num,
4778     mac_prop_info_handle_t prh)
4779 {
4780         nxge_t          *nxgep = barg;
4781         p_nxge_stats_t  statsp = nxgep->statsp;
4782 
4783         /*
4784          * By default permissions are read/write unless specified
4785          * otherwise by the driver.
4786          */
4787 
4788         switch (pr_num) {
4789         case MAC_PROP_DUPLEX:
4790         case MAC_PROP_SPEED:
4791         case MAC_PROP_STATUS:
4792         case MAC_PROP_EN_1000HDX_CAP:
4793         case MAC_PROP_EN_100HDX_CAP:
4794         case MAC_PROP_EN_10HDX_CAP:
4795         case MAC_PROP_ADV_1000FDX_CAP:
4796         case MAC_PROP_ADV_1000HDX_CAP:
4797         case MAC_PROP_ADV_100FDX_CAP:
4798         case MAC_PROP_ADV_100HDX_CAP:
4799         case MAC_PROP_ADV_10FDX_CAP:
4800         case MAC_PROP_ADV_10HDX_CAP:
4801                 /*
4802                  * Note that read-only properties don't need to
4803                  * provide default values since they cannot be
4804                  * changed by the administrator.
4805                  */
4806                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
4807                 break;
4808 
4809         case MAC_PROP_EN_1000FDX_CAP:
4810         case MAC_PROP_EN_100FDX_CAP:
4811         case MAC_PROP_EN_10FDX_CAP:
4812                 mac_prop_info_set_default_uint8(prh, 1);
4813                 break;
4814 
4815         case MAC_PROP_AUTONEG:
4816                 mac_prop_info_set_default_uint8(prh, 1);
4817                 break;
4818 
4819         case MAC_PROP_FLOWCTRL:
4820                 mac_prop_info_set_default_link_flowctrl(prh, LINK_FLOWCTRL_RX);
4821                 break;
4822 
4823         case MAC_PROP_MTU:
4824                 mac_prop_info_set_range_uint32(prh,
4825                     NXGE_DEFAULT_MTU, NXGE_MAXIMUM_MTU);
4826                 break;
4827 
4828         case MAC_PROP_PRIVATE:
4829                 nxge_priv_propinfo(pr_name, prh);
4830                 break;
4831         }
4832 
4833         mutex_enter(nxgep->genlock);
4834         if (statsp->port_stats.lb_mode != nxge_lb_normal &&
4835             nxge_param_locked(pr_num)) {
4836                 /*
4837                  * Some properties are locked (read-only) while the
4838                  * device is in any sort of loopback mode.
4839                  */
4840                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
4841         }
4842         mutex_exit(nxgep->genlock);
4843 }
4844 
4845 static void
4846 nxge_priv_propinfo(const char *pr_name, mac_prop_info_handle_t prh)
4847 {
4848         char valstr[64];
4849 
4850         bzero(valstr, sizeof (valstr));
4851 
4852         if (strcmp(pr_name, "_function_number") == 0 ||
4853             strcmp(pr_name, "_fw_version") == 0 ||
4854             strcmp(pr_name, "_port_mode") == 0 ||
4855             strcmp(pr_name, "_hot_swap_phy") == 0) {
4856                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
4857 
4858         } else if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
4859                 (void) snprintf(valstr, sizeof (valstr),
4860                     "%d", RXDMA_RCR_TO_DEFAULT);
4861 
4862         } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
4863                 (void) snprintf(valstr, sizeof (valstr),
4864                     "%d", RXDMA_RCR_PTHRES_DEFAULT);
4865 
4866         } else  if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 ||
4867             strcmp(pr_name, "_class_opt_ipv4_udp") == 0 ||
4868             strcmp(pr_name, "_class_opt_ipv4_ah") == 0 ||
4869             strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 ||
4870             strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 ||
4871             strcmp(pr_name, "_class_opt_ipv6_udp") == 0 ||
4872             strcmp(pr_name, "_class_opt_ipv6_ah") == 0 ||
4873             strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
4874                 (void) snprintf(valstr, sizeof (valstr), "%x",
4875                     NXGE_CLASS_FLOW_GEN_SERVER);
4876 
4877         } else if (strcmp(pr_name, "_soft_lso_enable") == 0) {
4878                 (void) snprintf(valstr, sizeof (valstr), "%d", 0);
4879 
4880         } else  if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) {
4881                 (void) snprintf(valstr, sizeof (valstr), "%d", 1);
4882 
4883         } else if (strcmp(pr_name, "_adv_pause_cap") == 0) {
4884                 (void) snprintf(valstr, sizeof (valstr), "%d", 1);
4885         }
4886 
4887         if (strlen(valstr) > 0)
4888                 mac_prop_info_set_default_str(prh, valstr);
4889 }
4890 
4891 /* ARGSUSED */
4892 static int
4893 nxge_set_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize,
4894     const void *pr_val)
4895 {
4896         p_nxge_param_t  param_arr = nxgep->param_arr;
4897         int             err = 0;
4898         long            result;
4899 
4900         NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4901             "==> nxge_set_priv_prop: name %s", pr_name));
4902 
4903         /* Blanking */
4904         if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
4905                 err = nxge_param_rx_intr_time(nxgep, NULL, NULL,
4906                     (char *)pr_val,
4907                     (caddr_t)&param_arr[param_rxdma_intr_time]);
4908                 if (err) {
4909                         NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4910                             "<== nxge_set_priv_prop: "
4911                             "unable to set (%s)", pr_name));
4912                         err = EINVAL;
4913                 } else {
4914                         err = 0;
4915                         NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4916                             "<== nxge_set_priv_prop: "
4917                             "set (%s)", pr_name));
4918                 }
4919 
4920                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4921                     "<== nxge_set_priv_prop: name %s (value %d)",
4922                     pr_name, result));
4923 
4924                 return (err);
4925         }
4926 
4927         if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
4928                 err = nxge_param_rx_intr_pkts(nxgep, NULL, NULL,
4929                     (char *)pr_val,
4930                     (caddr_t)&param_arr[param_rxdma_intr_pkts]);
4931                 if (err) {
4932                         NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4933                             "<== nxge_set_priv_prop: "
4934                             "unable to set (%s)", pr_name));
4935                         err = EINVAL;
4936                 } else {
4937                         err = 0;
4938                         NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4939                             "<== nxge_set_priv_prop: "
4940                             "set (%s)", pr_name));
4941                 }
4942 
4943                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4944                     "<== nxge_set_priv_prop: name %s (value %d)",
4945                     pr_name, result));
4946 
4947                 return (err);
4948         }
4949 
4950         /* Classification */
4951         if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
4952                 if (pr_val == NULL) {
4953                         err = EINVAL;
4954                         return (err);
4955                 }
4956                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
4957 
4958                 err = nxge_param_set_ip_opt(nxgep, NULL,
4959                     NULL, (char *)pr_val,
4960                     (caddr_t)&param_arr[param_class_opt_ipv4_tcp]);
4961 
4962                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4963                     "<== nxge_set_priv_prop: name %s (value 0x%x)",
4964                     pr_name, result));
4965 
4966                 return (err);
4967         }
4968 
4969         if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
4970                 if (pr_val == NULL) {
4971                         err = EINVAL;
4972                         return (err);
4973                 }
4974                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
4975 
4976                 err = nxge_param_set_ip_opt(nxgep, NULL,
4977                     NULL, (char *)pr_val,
4978                     (caddr_t)&param_arr[param_class_opt_ipv4_udp]);
4979 
4980                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4981                     "<== nxge_set_priv_prop: name %s (value 0x%x)",
4982                     pr_name, result));
4983 
4984                 return (err);
4985         }
4986         if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
4987                 if (pr_val == NULL) {
4988                         err = EINVAL;
4989                         return (err);
4990                 }
4991                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
4992 
4993                 err = nxge_param_set_ip_opt(nxgep, NULL,
4994                     NULL, (char *)pr_val,
4995                     (caddr_t)&param_arr[param_class_opt_ipv4_ah]);
4996 
4997                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4998                     "<== nxge_set_priv_prop: name %s (value 0x%x)",
4999                     pr_name, result));
5000 
5001                 return (err);
5002         }
5003         if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
5004                 if (pr_val == NULL) {
5005                         err = EINVAL;
5006                         return (err);
5007                 }
5008                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5009 
5010                 err = nxge_param_set_ip_opt(nxgep, NULL,
5011                     NULL, (char *)pr_val,
5012                     (caddr_t)&param_arr[param_class_opt_ipv4_sctp]);
5013 
5014                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5015                     "<== nxge_set_priv_prop: name %s (value 0x%x)",
5016                     pr_name, result));
5017 
5018                 return (err);
5019         }
5020 
5021         if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
5022                 if (pr_val == NULL) {
5023                         err = EINVAL;
5024                         return (err);
5025                 }
5026                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5027 
5028                 err = nxge_param_set_ip_opt(nxgep, NULL,
5029                     NULL, (char *)pr_val,
5030                     (caddr_t)&param_arr[param_class_opt_ipv6_tcp]);
5031 
5032                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5033                     "<== nxge_set_priv_prop: name %s (value 0x%x)",
5034                     pr_name, result));
5035 
5036                 return (err);
5037         }
5038 
5039         if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
5040                 if (pr_val == NULL) {
5041                         err = EINVAL;
5042                         return (err);
5043                 }
5044                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5045 
5046                 err = nxge_param_set_ip_opt(nxgep, NULL,
5047                     NULL, (char *)pr_val,
5048                     (caddr_t)&param_arr[param_class_opt_ipv6_udp]);
5049 
5050                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5051                     "<== nxge_set_priv_prop: name %s (value 0x%x)",
5052                     pr_name, result));
5053 
5054                 return (err);
5055         }
5056         if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
5057                 if (pr_val == NULL) {
5058                         err = EINVAL;
5059                         return (err);
5060                 }
5061                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5062 
5063                 err = nxge_param_set_ip_opt(nxgep, NULL,
5064                     NULL, (char *)pr_val,
5065                     (caddr_t)&param_arr[param_class_opt_ipv6_ah]);
5066 
5067                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5068                     "<== nxge_set_priv_prop: name %s (value 0x%x)",
5069                     pr_name, result));
5070 
5071                 return (err);
5072         }
5073         if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
5074                 if (pr_val == NULL) {
5075                         err = EINVAL;
5076                         return (err);
5077                 }
5078                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5079 
5080                 err = nxge_param_set_ip_opt(nxgep, NULL,
5081                     NULL, (char *)pr_val,
5082                     (caddr_t)&param_arr[param_class_opt_ipv6_sctp]);
5083 
5084                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5085                     "<== nxge_set_priv_prop: name %s (value 0x%x)",
5086                     pr_name, result));
5087 
5088                 return (err);
5089         }
5090 
5091         if (strcmp(pr_name, "_soft_lso_enable") == 0) {
5092                 if (pr_val == NULL) {
5093                         NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5094                             "==> nxge_set_priv_prop: name %s (null)", pr_name));
5095                         err = EINVAL;
5096                         return (err);
5097                 }
5098 
5099                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5100                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5101                     "<== nxge_set_priv_prop: name %s "
5102                     "(lso %d pr_val %s value %d)",
5103                     pr_name, nxgep->soft_lso_enable, pr_val, result));
5104 
5105                 if (result > 1 || result < 0) {
5106                         err = EINVAL;
5107                 } else {
5108                         if (nxgep->soft_lso_enable == (uint32_t)result) {
5109                                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5110                                     "no change (%d %d)",
5111                                     nxgep->soft_lso_enable, result));
5112                                 return (0);
5113                         }
5114                 }
5115 
5116                 nxgep->soft_lso_enable = (int)result;
5117 
5118                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5119                     "<== nxge_set_priv_prop: name %s (value %d)",
5120                     pr_name, result));
5121 
5122                 return (err);
5123         }
5124         /*
5125          * Commands like "ndd -set /dev/nxge0 adv_10gfdx_cap 1" cause the
5126          * following code to be executed.
5127          */
5128         if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) {
5129                 err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val,
5130                     (caddr_t)&param_arr[param_anar_10gfdx]);
5131                 return (err);
5132         }
5133         if (strcmp(pr_name, "_adv_pause_cap") == 0) {
5134                 err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val,
5135                     (caddr_t)&param_arr[param_anar_pause]);
5136                 return (err);
5137         }
5138 
5139         return (EINVAL);
5140 }
5141 
5142 static int
5143 nxge_get_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize,
5144     void *pr_val)
5145 {
5146         p_nxge_param_t  param_arr = nxgep->param_arr;
5147         char            valstr[MAXNAMELEN];
5148         int             err = EINVAL;
5149         uint_t          strsize;
5150 
5151         NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5152             "==> nxge_get_priv_prop: property %s", pr_name));
5153 
5154         /* function number */
5155         if (strcmp(pr_name, "_function_number") == 0) {
5156                 (void) snprintf(valstr, sizeof (valstr), "%d",
5157                     nxgep->function_num);
5158                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5159                     "==> nxge_get_priv_prop: name %s "
5160                     "(value %d valstr %s)",
5161                     pr_name, nxgep->function_num, valstr));
5162 
5163                 err = 0;
5164                 goto done;
5165         }
5166 
5167         /* Neptune firmware version */
5168         if (strcmp(pr_name, "_fw_version") == 0) {
5169                 (void) snprintf(valstr, sizeof (valstr), "%s",
5170                     nxgep->vpd_info.ver);
5171                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5172                     "==> nxge_get_priv_prop: name %s "
5173                     "(value %d valstr %s)",
5174                     pr_name, nxgep->vpd_info.ver, valstr));
5175 
5176                 err = 0;
5177                 goto done;
5178         }
5179 
5180         /* port PHY mode */
5181         if (strcmp(pr_name, "_port_mode") == 0) {
5182                 switch (nxgep->mac.portmode) {
5183                 case PORT_1G_COPPER:
5184                         (void) snprintf(valstr, sizeof (valstr), "1G copper %s",
5185                             nxgep->hot_swappable_phy ?
5186                             "[Hot Swappable]" : "");
5187                         break;
5188                 case PORT_1G_FIBER:
5189                         (void) snprintf(valstr, sizeof (valstr), "1G fiber %s",
5190                             nxgep->hot_swappable_phy ?
5191                             "[hot swappable]" : "");
5192                         break;
5193                 case PORT_10G_COPPER:
5194                         (void) snprintf(valstr, sizeof (valstr),
5195                             "10G copper %s",
5196                             nxgep->hot_swappable_phy ?
5197                             "[hot swappable]" : "");
5198                         break;
5199                 case PORT_10G_FIBER:
5200                         (void) snprintf(valstr, sizeof (valstr), "10G fiber %s",
5201                             nxgep->hot_swappable_phy ?
5202                             "[hot swappable]" : "");
5203                         break;
5204                 case PORT_10G_SERDES:
5205                         (void) snprintf(valstr, sizeof (valstr),
5206                             "10G serdes %s", nxgep->hot_swappable_phy ?
5207                             "[hot swappable]" : "");
5208                         break;
5209                 case PORT_1G_SERDES:
5210                         (void) snprintf(valstr, sizeof (valstr), "1G serdes %s",
5211                             nxgep->hot_swappable_phy ?
5212                             "[hot swappable]" : "");
5213                         break;
5214                 case PORT_1G_TN1010:
5215                         (void) snprintf(valstr, sizeof (valstr),
5216                             "1G TN1010 copper %s", nxgep->hot_swappable_phy ?
5217                             "[hot swappable]" : "");
5218                         break;
5219                 case PORT_10G_TN1010:
5220                         (void) snprintf(valstr, sizeof (valstr),
5221                             "10G TN1010 copper %s", nxgep->hot_swappable_phy ?
5222                             "[hot swappable]" : "");
5223                         break;
5224                 case PORT_1G_RGMII_FIBER:
5225                         (void) snprintf(valstr, sizeof (valstr),
5226                             "1G rgmii fiber %s", nxgep->hot_swappable_phy ?
5227                             "[hot swappable]" : "");
5228                         break;
5229                 case PORT_HSP_MODE:
5230                         (void) snprintf(valstr, sizeof (valstr),
5231                             "phy not present[hot swappable]");
5232                         break;
5233                 default:
5234                         (void) snprintf(valstr, sizeof (valstr), "unknown %s",
5235                             nxgep->hot_swappable_phy ?
5236                             "[hot swappable]" : "");
5237                         break;
5238                 }
5239 
5240                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5241                     "==> nxge_get_priv_prop: name %s (value %s)",
5242                     pr_name, valstr));
5243 
5244                 err = 0;
5245                 goto done;
5246         }
5247 
5248         /* Hot swappable PHY */
5249         if (strcmp(pr_name, "_hot_swap_phy") == 0) {
5250                 (void) snprintf(valstr, sizeof (valstr), "%s",
5251                     nxgep->hot_swappable_phy ?
5252                     "yes" : "no");
5253 
5254                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5255                     "==> nxge_get_priv_prop: name %s "
5256                     "(value %d valstr %s)",
5257                     pr_name, nxgep->hot_swappable_phy, valstr));
5258 
5259                 err = 0;
5260                 goto done;
5261         }
5262 
5263 
5264         /* Receive Interrupt Blanking Parameters */
5265         if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
5266                 err = 0;
5267                 (void) snprintf(valstr, sizeof (valstr), "%d",
5268                     nxgep->intr_timeout);
5269                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5270                     "==> nxge_get_priv_prop: name %s (value %d)",
5271                     pr_name,
5272                     (uint32_t)nxgep->intr_timeout));
5273                 goto done;
5274         }
5275 
5276         if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
5277                 err = 0;
5278                 (void) snprintf(valstr, sizeof (valstr), "%d",
5279                     nxgep->intr_threshold);
5280                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5281                     "==> nxge_get_priv_prop: name %s (value %d)",
5282                     pr_name, (uint32_t)nxgep->intr_threshold));
5283 
5284                 goto done;
5285         }
5286 
5287         /* Classification and Load Distribution Configuration */
5288         if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
5289                 err = nxge_dld_get_ip_opt(nxgep,
5290                     (caddr_t)&param_arr[param_class_opt_ipv4_tcp]);
5291 
5292                 (void) snprintf(valstr, sizeof (valstr), "%x",
5293                     (int)param_arr[param_class_opt_ipv4_tcp].value);
5294 
5295                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5296                     "==> nxge_get_priv_prop: %s", valstr));
5297                 goto done;
5298         }
5299 
5300         if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
5301                 err = nxge_dld_get_ip_opt(nxgep,
5302                     (caddr_t)&param_arr[param_class_opt_ipv4_udp]);
5303 
5304                 (void) snprintf(valstr, sizeof (valstr), "%x",
5305                     (int)param_arr[param_class_opt_ipv4_udp].value);
5306 
5307                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5308                     "==> nxge_get_priv_prop: %s", valstr));
5309                 goto done;
5310         }
5311         if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
5312                 err = nxge_dld_get_ip_opt(nxgep,
5313                     (caddr_t)&param_arr[param_class_opt_ipv4_ah]);
5314 
5315                 (void) snprintf(valstr, sizeof (valstr), "%x",
5316                     (int)param_arr[param_class_opt_ipv4_ah].value);
5317 
5318                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5319                     "==> nxge_get_priv_prop: %s", valstr));
5320                 goto done;
5321         }
5322 
5323         if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
5324                 err = nxge_dld_get_ip_opt(nxgep,
5325                     (caddr_t)&param_arr[param_class_opt_ipv4_sctp]);
5326 
5327                 (void) snprintf(valstr, sizeof (valstr), "%x",
5328                     (int)param_arr[param_class_opt_ipv4_sctp].value);
5329 
5330                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5331                     "==> nxge_get_priv_prop: %s", valstr));
5332                 goto done;
5333         }
5334 
5335         if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
5336                 err = nxge_dld_get_ip_opt(nxgep,
5337                     (caddr_t)&param_arr[param_class_opt_ipv6_tcp]);
5338 
5339                 (void) snprintf(valstr, sizeof (valstr), "%x",
5340                     (int)param_arr[param_class_opt_ipv6_tcp].value);
5341 
5342                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5343                     "==> nxge_get_priv_prop: %s", valstr));
5344                 goto done;
5345         }
5346 
5347         if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
5348                 err = nxge_dld_get_ip_opt(nxgep,
5349                     (caddr_t)&param_arr[param_class_opt_ipv6_udp]);
5350 
5351                 (void) snprintf(valstr, sizeof (valstr), "%x",
5352                     (int)param_arr[param_class_opt_ipv6_udp].value);
5353 
5354                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5355                     "==> nxge_get_priv_prop: %s", valstr));
5356                 goto done;
5357         }
5358 
5359         if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
5360                 err = nxge_dld_get_ip_opt(nxgep,
5361                     (caddr_t)&param_arr[param_class_opt_ipv6_ah]);
5362 
5363                 (void) snprintf(valstr, sizeof (valstr), "%x",
5364                     (int)param_arr[param_class_opt_ipv6_ah].value);
5365 
5366                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5367                     "==> nxge_get_priv_prop: %s", valstr));
5368                 goto done;
5369         }
5370 
5371         if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
5372                 err = nxge_dld_get_ip_opt(nxgep,
5373                     (caddr_t)&param_arr[param_class_opt_ipv6_sctp]);
5374 
5375                 (void) snprintf(valstr, sizeof (valstr), "%x",
5376                     (int)param_arr[param_class_opt_ipv6_sctp].value);
5377 
5378                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5379                     "==> nxge_get_priv_prop: %s", valstr));
5380                 goto done;
5381         }
5382 
5383         /* Software LSO */
5384         if (strcmp(pr_name, "_soft_lso_enable") == 0) {
5385                 (void) snprintf(valstr, sizeof (valstr),
5386                     "%d", nxgep->soft_lso_enable);
5387                 err = 0;
5388                 NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5389                     "==> nxge_get_priv_prop: name %s (value %d)",
5390                     pr_name, nxgep->soft_lso_enable));
5391 
5392                 goto done;
5393         }
5394         if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) {
5395                 err = 0;
5396                 if (nxgep->param_arr[param_anar_10gfdx].value != 0) {
5397                         (void) snprintf(valstr, sizeof (valstr), "%d", 1);
5398                         goto done;
5399                 } else {
5400                         (void) snprintf(valstr, sizeof (valstr), "%d", 0);
5401                         goto done;
5402                 }
5403         }
5404         if (strcmp(pr_name, "_adv_pause_cap") == 0) {
5405                 err = 0;
5406                 if (nxgep->param_arr[param_anar_pause].value != 0) {
5407                         (void) snprintf(valstr, sizeof (valstr), "%d", 1);
5408                         goto done;
5409                 } else {
5410                         (void) snprintf(valstr, sizeof (valstr), "%d", 0);
5411                         goto done;
5412                 }
5413         }
5414 
5415 done:
5416         if (err == 0) {
5417                 strsize = (uint_t)strlen(valstr);
5418                 if (pr_valsize < strsize) {
5419                         err = ENOBUFS;
5420                 } else {
5421                         (void) strlcpy(pr_val, valstr, pr_valsize);
5422                 }
5423         }
5424 
5425         NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5426             "<== nxge_get_priv_prop: return %d", err));
5427         return (err);
5428 }
5429 
5430 /*
5431  * Module loading and removing entry points.
5432  */
5433 
5434 DDI_DEFINE_STREAM_OPS(nxge_dev_ops, nulldev, nulldev, nxge_attach, nxge_detach,
5435     nodev, NULL, D_MP, NULL, nxge_quiesce);
5436 
5437 #define NXGE_DESC_VER           "Sun NIU 10Gb Ethernet"
5438 
5439 /*
5440  * Module linkage information for the kernel.
5441  */
5442 static struct modldrv   nxge_modldrv = {
5443         &mod_driverops,
5444         NXGE_DESC_VER,
5445         &nxge_dev_ops
5446 };
5447 
5448 static struct modlinkage modlinkage = {
5449         MODREV_1, (void *) &nxge_modldrv, NULL
5450 };
5451 
5452 int
5453 _init(void)
5454 {
5455         int             status;
5456 
5457         MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL);
5458 
5459         NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init"));
5460 
5461         mac_init_ops(&nxge_dev_ops, "nxge");
5462 
5463         status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0);
5464         if (status != 0) {
5465                 NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
5466                     "failed to init device soft state"));
5467                 goto _init_exit;
5468         }
5469 
5470         status = mod_install(&modlinkage);
5471         if (status != 0) {
5472                 ddi_soft_state_fini(&nxge_list);
5473                 NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed"));
5474                 goto _init_exit;
5475         }
5476 
5477         MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL);
5478 
5479         NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status));
5480         return (status);
5481 
5482 _init_exit:
5483         NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status));
5484         MUTEX_DESTROY(&nxgedebuglock);
5485         return (status);
5486 }
5487 
5488 int
5489 _fini(void)
5490 {
5491         int             status;
5492 
5493         NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini"));
5494         NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove"));
5495 
5496         if (nxge_mblks_pending)
5497                 return (EBUSY);
5498 
5499         status = mod_remove(&modlinkage);
5500         if (status != DDI_SUCCESS) {
5501                 NXGE_DEBUG_MSG((NULL, MOD_CTL,
5502                     "Module removal failed 0x%08x",
5503                     status));
5504                 goto _fini_exit;
5505         }
5506 
5507         mac_fini_ops(&nxge_dev_ops);
5508 
5509         ddi_soft_state_fini(&nxge_list);
5510 
5511         NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status));
5512 
5513         MUTEX_DESTROY(&nxge_common_lock);
5514         MUTEX_DESTROY(&nxgedebuglock);
5515         return (status);
5516 
5517 _fini_exit:
5518         NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status));
5519         return (status);
5520 }
5521 
5522 int
5523 _info(struct modinfo *modinfop)
5524 {
5525         int             status;
5526 
5527         NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info"));
5528         status = mod_info(&modlinkage, modinfop);
5529         NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status));
5530 
5531         return (status);
5532 }
5533 
5534 /*ARGSUSED*/
5535 static int
5536 nxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num)
5537 {
5538         p_nxge_ring_handle_t    rhp = (p_nxge_ring_handle_t)rdriver;
5539         p_nxge_t                nxgep = rhp->nxgep;
5540         uint32_t                channel;
5541         p_tx_ring_t             ring;
5542 
5543         channel = nxgep->pt_config.hw_config.tdc.start + rhp->index;
5544         ring = nxgep->tx_rings->rings[channel];
5545 
5546         MUTEX_ENTER(&ring->lock);
5547         ASSERT(ring->tx_ring_handle == NULL);
5548         ring->tx_ring_handle = rhp->ring_handle;
5549         MUTEX_EXIT(&ring->lock);
5550 
5551         return (0);
5552 }
5553 
5554 static void
5555 nxge_tx_ring_stop(mac_ring_driver_t rdriver)
5556 {
5557         p_nxge_ring_handle_t    rhp = (p_nxge_ring_handle_t)rdriver;
5558         p_nxge_t                nxgep = rhp->nxgep;
5559         uint32_t                channel;
5560         p_tx_ring_t             ring;
5561 
5562         channel = nxgep->pt_config.hw_config.tdc.start + rhp->index;
5563         ring = nxgep->tx_rings->rings[channel];
5564 
5565         MUTEX_ENTER(&ring->lock);
5566         ASSERT(ring->tx_ring_handle != NULL);
5567         ring->tx_ring_handle = (mac_ring_handle_t)NULL;
5568         MUTEX_EXIT(&ring->lock);
5569 }
5570 
5571 int
5572 nxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num)
5573 {
5574         p_nxge_ring_handle_t    rhp = (p_nxge_ring_handle_t)rdriver;
5575         p_nxge_t                nxgep = rhp->nxgep;
5576         uint32_t                channel;
5577         p_rx_rcr_ring_t         ring;
5578         int                     i;
5579 
5580         channel = nxgep->pt_config.hw_config.start_rdc + rhp->index;
5581         ring =  nxgep->rx_rcr_rings->rcr_rings[channel];
5582 
5583         MUTEX_ENTER(&ring->lock);
5584 
5585         if (ring->started) {
5586                 ASSERT(ring->started == B_FALSE);
5587                 MUTEX_EXIT(&ring->lock);
5588                 return (0);
5589         }
5590 
5591         /* set rcr_ring */
5592         for (i = 0; i < nxgep->ldgvp->maxldvs; i++) {
5593                 if ((nxgep->ldgvp->ldvp[i].is_rxdma) &&
5594                     (nxgep->ldgvp->ldvp[i].channel == channel)) {
5595                         ring->ldvp = &nxgep->ldgvp->ldvp[i];
5596                         ring->ldgp = nxgep->ldgvp->ldvp[i].ldgp;
5597                 }
5598         }
5599 
5600         ring->rcr_mac_handle = rhp->ring_handle;
5601         ring->rcr_gen_num = mr_gen_num;
5602         ring->started = B_TRUE;
5603         rhp->ring_gen_num = mr_gen_num;
5604         MUTEX_EXIT(&ring->lock);
5605 
5606         return (0);
5607 }
5608 
5609 static void
5610 nxge_rx_ring_stop(mac_ring_driver_t rdriver)
5611 {
5612         p_nxge_ring_handle_t    rhp = (p_nxge_ring_handle_t)rdriver;
5613         p_nxge_t                nxgep = rhp->nxgep;
5614         uint32_t                channel;
5615         p_rx_rcr_ring_t         ring;
5616 
5617         channel = nxgep->pt_config.hw_config.start_rdc + rhp->index;
5618         ring =  nxgep->rx_rcr_rings->rcr_rings[channel];
5619 
5620         MUTEX_ENTER(&ring->lock);
5621         ASSERT(ring->started == B_TRUE);
5622         ring->rcr_mac_handle = NULL;
5623         ring->ldvp = NULL;
5624         ring->ldgp = NULL;
5625         ring->started = B_FALSE;
5626         MUTEX_EXIT(&ring->lock);
5627 }
5628 
5629 static int
5630 nxge_ring_get_htable_idx(p_nxge_t nxgep, mac_ring_type_t type, uint32_t channel)
5631 {
5632         int     i;
5633 
5634 #if defined(sun4v)
5635         if (isLDOMguest(nxgep)) {
5636                 return (nxge_hio_get_dc_htable_idx(nxgep,
5637                     (type == MAC_RING_TYPE_TX) ? VP_BOUND_TX : VP_BOUND_RX,
5638                     channel));
5639         }
5640 #endif
5641 
5642         ASSERT(nxgep->ldgvp != NULL);
5643 
5644         switch (type) {
5645         case MAC_RING_TYPE_TX:
5646                 for (i = 0; i < nxgep->ldgvp->maxldvs; i++) {
5647                         if ((nxgep->ldgvp->ldvp[i].is_txdma) &&
5648                             (nxgep->ldgvp->ldvp[i].channel == channel)) {
5649                                 return ((int)
5650                                     nxgep->ldgvp->ldvp[i].ldgp->htable_idx);
5651                         }
5652                 }
5653                 break;
5654 
5655         case MAC_RING_TYPE_RX:
5656                 for (i = 0; i < nxgep->ldgvp->maxldvs; i++) {
5657                         if ((nxgep->ldgvp->ldvp[i].is_rxdma) &&
5658                             (nxgep->ldgvp->ldvp[i].channel == channel)) {
5659                                 return ((int)
5660                                     nxgep->ldgvp->ldvp[i].ldgp->htable_idx);
5661                         }
5662                 }
5663         }
5664 
5665         return (-1);
5666 }
5667 
5668 /*
5669  * Callback funtion for MAC layer to register all rings.
5670  */
5671 static void
5672 nxge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index,
5673     const int index, mac_ring_info_t *infop, mac_ring_handle_t rh)
5674 {
5675         p_nxge_t                nxgep = (p_nxge_t)arg;
5676         p_nxge_hw_pt_cfg_t      p_cfgp = &nxgep->pt_config.hw_config;
5677         p_nxge_intr_t           intrp;
5678         uint32_t                channel;
5679         int                     htable_idx;
5680         p_nxge_ring_handle_t    rhandlep;
5681 
5682         ASSERT(nxgep != NULL);
5683         ASSERT(p_cfgp != NULL);
5684         ASSERT(infop != NULL);
5685 
5686         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
5687             "==> nxge_fill_ring 0x%x index %d", rtype, index));
5688 
5689 
5690         switch (rtype) {
5691         case MAC_RING_TYPE_TX: {
5692                 mac_intr_t      *mintr = &infop->mri_intr;
5693 
5694                 NXGE_DEBUG_MSG((nxgep, TX_CTL,
5695                     "==> nxge_fill_ring (TX) 0x%x index %d ntdcs %d",
5696                     rtype, index, p_cfgp->tdc.count));
5697 
5698                 ASSERT((index >= 0) && (index < p_cfgp->tdc.count));
5699                 rhandlep = &nxgep->tx_ring_handles[index];
5700                 rhandlep->nxgep = nxgep;
5701                 rhandlep->index = index;
5702                 rhandlep->ring_handle = rh;
5703 
5704                 channel = nxgep->pt_config.hw_config.tdc.start + index;
5705                 rhandlep->channel = channel;
5706                 intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
5707                 htable_idx = nxge_ring_get_htable_idx(nxgep, rtype,
5708                     channel);
5709                 if (htable_idx >= 0)
5710                         mintr->mi_ddi_handle = intrp->htable[htable_idx];
5711                 else
5712                         mintr->mi_ddi_handle = NULL;
5713 
5714                 infop->mri_driver = (mac_ring_driver_t)rhandlep;
5715                 infop->mri_start = nxge_tx_ring_start;
5716                 infop->mri_stop = nxge_tx_ring_stop;
5717                 infop->mri_tx = nxge_tx_ring_send;
5718                 infop->mri_stat = nxge_tx_ring_stat;
5719                 infop->mri_flags = MAC_RING_TX_SERIALIZE;
5720                 break;
5721         }
5722 
5723         case MAC_RING_TYPE_RX: {
5724                 mac_intr_t              nxge_mac_intr;
5725                 int                     nxge_rindex;
5726                 p_nxge_intr_t           intrp;
5727 
5728                 intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
5729 
5730                 NXGE_DEBUG_MSG((nxgep, RX_CTL,
5731                     "==> nxge_fill_ring (RX) 0x%x index %d nrdcs %d",
5732                     rtype, index, p_cfgp->max_rdcs));
5733 
5734                 /*
5735                  * 'index' is the ring index within the group.
5736                  * Find the ring index in the nxge instance.
5737                  */
5738                 nxge_rindex = nxge_get_rxring_index(nxgep, rg_index, index);
5739                 channel = nxgep->pt_config.hw_config.start_rdc + index;
5740                 intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
5741 
5742                 ASSERT((nxge_rindex >= 0) && (nxge_rindex < p_cfgp->max_rdcs));
5743                 rhandlep = &nxgep->rx_ring_handles[nxge_rindex];
5744                 rhandlep->nxgep = nxgep;
5745                 rhandlep->index = nxge_rindex;
5746                 rhandlep->ring_handle = rh;
5747                 rhandlep->channel = channel;
5748 
5749                 /*
5750                  * Entrypoint to enable interrupt (disable poll) and
5751                  * disable interrupt (enable poll).
5752                  */
5753                 bzero(&nxge_mac_intr, sizeof (nxge_mac_intr));
5754                 nxge_mac_intr.mi_handle = (mac_intr_handle_t)rhandlep;
5755                 nxge_mac_intr.mi_enable = (mac_intr_enable_t)nxge_disable_poll;
5756                 nxge_mac_intr.mi_disable = (mac_intr_disable_t)nxge_enable_poll;
5757 
5758                 htable_idx =  nxge_ring_get_htable_idx(nxgep, rtype,
5759                     channel);
5760                 if (htable_idx >= 0)
5761                         nxge_mac_intr.mi_ddi_handle = intrp->htable[htable_idx];
5762                 else
5763                         nxge_mac_intr.mi_ddi_handle = NULL;
5764 
5765                 infop->mri_driver = (mac_ring_driver_t)rhandlep;
5766                 infop->mri_start = nxge_rx_ring_start;
5767                 infop->mri_stop = nxge_rx_ring_stop;
5768                 infop->mri_intr = nxge_mac_intr;
5769                 infop->mri_poll = nxge_rx_poll;
5770                 infop->mri_stat = nxge_rx_ring_stat;
5771                 infop->mri_flags = MAC_RING_RX_ENQUEUE;
5772                 break;
5773         }
5774 
5775         default:
5776                 break;
5777         }
5778 
5779         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_fill_ring 0x%x", rtype));
5780 }
5781 
5782 static void
5783 nxge_group_add_ring(mac_group_driver_t gh, mac_ring_driver_t rh,
5784     mac_ring_type_t type)
5785 {
5786         nxge_ring_group_t       *rgroup = (nxge_ring_group_t *)gh;
5787         nxge_ring_handle_t      *rhandle = (nxge_ring_handle_t *)rh;
5788         nxge_t                  *nxge;
5789         nxge_grp_t              *grp;
5790         nxge_rdc_grp_t          *rdc_grp;
5791         uint16_t                channel;        /* device-wise ring id */
5792         int                     dev_gindex;
5793         int                     rv;
5794 
5795         nxge = rgroup->nxgep;
5796 
5797         switch (type) {
5798         case MAC_RING_TYPE_TX:
5799                 /*
5800                  * nxge_grp_dc_add takes a channel number which is a
5801                  * "devise" ring ID.
5802                  */
5803                 channel = nxge->pt_config.hw_config.tdc.start + rhandle->index;
5804 
5805                 /*
5806                  * Remove the ring from the default group
5807                  */
5808                 if (rgroup->gindex != 0) {
5809                         (void) nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel);
5810                 }
5811 
5812                 /*
5813                  * nxge->tx_set.group[] is an array of groups indexed by
5814                  * a "port" group ID.
5815                  */
5816                 grp = nxge->tx_set.group[rgroup->gindex];
5817                 rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel);
5818                 if (rv != 0) {
5819                         NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
5820                             "nxge_group_add_ring: nxge_grp_dc_add failed"));
5821                 }
5822                 break;
5823 
5824         case MAC_RING_TYPE_RX:
5825                 /*
5826                  * nxge->rx_set.group[] is an array of groups indexed by
5827                  * a "port" group ID.
5828                  */
5829                 grp = nxge->rx_set.group[rgroup->gindex];
5830 
5831                 dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid +
5832                     rgroup->gindex;
5833                 rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex];
5834 
5835                 /*
5836                  * nxge_grp_dc_add takes a channel number which is a
5837                  * "devise" ring ID.
5838                  */
5839                 channel = nxge->pt_config.hw_config.start_rdc + rhandle->index;
5840                 rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_RX, channel);
5841                 if (rv != 0) {
5842                         NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
5843                             "nxge_group_add_ring: nxge_grp_dc_add failed"));
5844                 }
5845 
5846                 rdc_grp->map |= (1 << channel);
5847                 rdc_grp->max_rdcs++;
5848 
5849                 (void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl);
5850                 break;
5851         }
5852 }
5853 
5854 static void
5855 nxge_group_rem_ring(mac_group_driver_t gh, mac_ring_driver_t rh,
5856     mac_ring_type_t type)
5857 {
5858         nxge_ring_group_t       *rgroup = (nxge_ring_group_t *)gh;
5859         nxge_ring_handle_t      *rhandle = (nxge_ring_handle_t *)rh;
5860         nxge_t                  *nxge;
5861         uint16_t                channel;        /* device-wise ring id */
5862         nxge_rdc_grp_t          *rdc_grp;
5863         int                     dev_gindex;
5864 
5865         nxge = rgroup->nxgep;
5866 
5867         switch (type) {
5868         case MAC_RING_TYPE_TX:
5869                 dev_gindex = nxge->pt_config.hw_config.def_mac_txdma_grpid +
5870                     rgroup->gindex;
5871                 channel = nxge->pt_config.hw_config.tdc.start + rhandle->index;
5872                 nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel);
5873 
5874                 /*
5875                  * Add the ring back to the default group
5876                  */
5877                 if (rgroup->gindex != 0) {
5878                         nxge_grp_t *grp;
5879                         grp = nxge->tx_set.group[0];
5880                         (void) nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel);
5881                 }
5882                 break;
5883 
5884         case MAC_RING_TYPE_RX:
5885                 dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid +
5886                     rgroup->gindex;
5887                 rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex];
5888                 channel = rdc_grp->start_rdc + rhandle->index;
5889                 nxge_grp_dc_remove(nxge, VP_BOUND_RX, channel);
5890 
5891                 rdc_grp->map &= ~(1 << channel);
5892                 rdc_grp->max_rdcs--;
5893 
5894                 (void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl);
5895                 break;
5896         }
5897 }
5898 
5899 
5900 /*ARGSUSED*/
5901 static nxge_status_t
5902 nxge_add_intrs(p_nxge_t nxgep)
5903 {
5904 
5905         int             intr_types;
5906         int             type = 0;
5907         int             ddi_status = DDI_SUCCESS;
5908         nxge_status_t   status = NXGE_OK;
5909 
5910         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs"));
5911 
5912         nxgep->nxge_intr_type.intr_registered = B_FALSE;
5913         nxgep->nxge_intr_type.intr_enabled = B_FALSE;
5914         nxgep->nxge_intr_type.msi_intx_cnt = 0;
5915         nxgep->nxge_intr_type.intr_added = 0;
5916         nxgep->nxge_intr_type.niu_msi_enable = B_FALSE;
5917         nxgep->nxge_intr_type.intr_type = 0;
5918 
5919         if (nxgep->niu_type == N2_NIU) {
5920                 nxgep->nxge_intr_type.niu_msi_enable = B_TRUE;
5921         } else if (nxge_msi_enable) {
5922                 nxgep->nxge_intr_type.niu_msi_enable = B_TRUE;
5923         }
5924 
5925         /* Get the supported interrupt types */
5926         if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types))
5927             != DDI_SUCCESS) {
5928                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: "
5929                     "ddi_intr_get_supported_types failed: status 0x%08x",
5930                     ddi_status));
5931                 return (NXGE_ERROR | NXGE_DDI_FAILED);
5932         }
5933         nxgep->nxge_intr_type.intr_types = intr_types;
5934 
5935         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
5936             "ddi_intr_get_supported_types: 0x%08x", intr_types));
5937 
5938         /*
5939          * Solaris MSIX is not supported yet. use MSI for now.
5940          * nxge_msi_enable (1):
5941          *      1 - MSI         2 - MSI-X       others - FIXED
5942          */
5943         switch (nxge_msi_enable) {
5944         default:
5945                 type = DDI_INTR_TYPE_FIXED;
5946                 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
5947                     "use fixed (intx emulation) type %08x",
5948                     type));
5949                 break;
5950 
5951         case 2:
5952                 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
5953                     "ddi_intr_get_supported_types: 0x%08x", intr_types));
5954                 if (intr_types & DDI_INTR_TYPE_MSIX) {
5955                         type = DDI_INTR_TYPE_MSIX;
5956                         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
5957                             "ddi_intr_get_supported_types: MSIX 0x%08x",
5958                             type));
5959                 } else if (intr_types & DDI_INTR_TYPE_MSI) {
5960                         type = DDI_INTR_TYPE_MSI;
5961                         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
5962                             "ddi_intr_get_supported_types: MSI 0x%08x",
5963                             type));
5964                 } else if (intr_types & DDI_INTR_TYPE_FIXED) {
5965                         type = DDI_INTR_TYPE_FIXED;
5966                         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
5967                             "ddi_intr_get_supported_types: MSXED0x%08x",
5968                             type));
5969                 }
5970                 break;
5971 
5972         case 1:
5973                 if (intr_types & DDI_INTR_TYPE_MSI) {
5974                         type = DDI_INTR_TYPE_MSI;
5975                         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
5976                             "ddi_intr_get_supported_types: MSI 0x%08x",
5977                             type));
5978                 } else if (intr_types & DDI_INTR_TYPE_MSIX) {
5979                         type = DDI_INTR_TYPE_MSIX;
5980                         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
5981                             "ddi_intr_get_supported_types: MSIX 0x%08x",
5982                             type));
5983                 } else if (intr_types & DDI_INTR_TYPE_FIXED) {
5984                         type = DDI_INTR_TYPE_FIXED;
5985                         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
5986                             "ddi_intr_get_supported_types: MSXED0x%08x",
5987                             type));
5988                 }
5989         }
5990 
5991         nxgep->nxge_intr_type.intr_type = type;
5992         if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI ||
5993             type == DDI_INTR_TYPE_FIXED) &&
5994             nxgep->nxge_intr_type.niu_msi_enable) {
5995                 if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) {
5996                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5997                             " nxge_add_intrs: "
5998                             " nxge_add_intrs_adv failed: status 0x%08x",
5999                             status));
6000                         return (status);
6001                 } else {
6002                         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
6003                             "interrupts registered : type %d", type));
6004                         nxgep->nxge_intr_type.intr_registered = B_TRUE;
6005 
6006                         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
6007                             "\nAdded advanced nxge add_intr_adv "
6008                             "intr type 0x%x\n", type));
6009 
6010                         return (status);
6011                 }
6012         }
6013 
6014         if (!nxgep->nxge_intr_type.intr_registered) {
6015                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: "
6016                     "failed to register interrupts"));
6017                 return (NXGE_ERROR | NXGE_DDI_FAILED);
6018         }
6019 
6020         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs"));
6021         return (status);
6022 }
6023 
6024 static nxge_status_t
6025 nxge_add_intrs_adv(p_nxge_t nxgep)
6026 {
6027         int             intr_type;
6028         p_nxge_intr_t   intrp;
6029 
6030         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv"));
6031 
6032         intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6033         intr_type = intrp->intr_type;
6034         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x",
6035             intr_type));
6036 
6037         switch (intr_type) {
6038         case DDI_INTR_TYPE_MSI: /* 0x2 */
6039         case DDI_INTR_TYPE_MSIX: /* 0x4 */
6040                 return (nxge_add_intrs_adv_type(nxgep, intr_type));
6041 
6042         case DDI_INTR_TYPE_FIXED: /* 0x1 */
6043                 return (nxge_add_intrs_adv_type_fix(nxgep, intr_type));
6044 
6045         default:
6046                 return (NXGE_ERROR);
6047         }
6048 }
6049 
6050 
6051 /*ARGSUSED*/
6052 static nxge_status_t
6053 nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type)
6054 {
6055         dev_info_t              *dip = nxgep->dip;
6056         p_nxge_ldg_t            ldgp;
6057         p_nxge_intr_t           intrp;
6058         uint_t                  *inthandler;
6059         void                    *arg1, *arg2;
6060         int                     behavior;
6061         int                     nintrs, navail, nrequest;
6062         int                     nactual, nrequired;
6063         int                     inum = 0;
6064         int                     x, y;
6065         int                     ddi_status = DDI_SUCCESS;
6066         nxge_status_t           status = NXGE_OK;
6067 
6068         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type"));
6069         intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6070         intrp->start_inum = 0;
6071 
6072         ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
6073         if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
6074                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6075                     "ddi_intr_get_nintrs() failed, status: 0x%x%, "
6076                     "nintrs: %d", ddi_status, nintrs));
6077                 return (NXGE_ERROR | NXGE_DDI_FAILED);
6078         }
6079 
6080         ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
6081         if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
6082                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6083                     "ddi_intr_get_navail() failed, status: 0x%x%, "
6084                     "nintrs: %d", ddi_status, navail));
6085                 return (NXGE_ERROR | NXGE_DDI_FAILED);
6086         }
6087 
6088         NXGE_DEBUG_MSG((nxgep, INT_CTL,
6089             "ddi_intr_get_navail() returned: nintrs %d, navail %d",
6090             nintrs, navail));
6091 
6092         /* PSARC/2007/453 MSI-X interrupt limit override */
6093         if (int_type == DDI_INTR_TYPE_MSIX) {
6094                 nrequest = nxge_create_msi_property(nxgep);
6095                 if (nrequest < navail) {
6096                         navail = nrequest;
6097                         NXGE_DEBUG_MSG((nxgep, INT_CTL,
6098                             "nxge_add_intrs_adv_type: nintrs %d "
6099                             "navail %d (nrequest %d)",
6100                             nintrs, navail, nrequest));
6101                 }
6102         }
6103 
6104         if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) {
6105                 /* MSI must be power of 2 */
6106                 if ((navail & 16) == 16) {
6107                         navail = 16;
6108                 } else if ((navail & 8) == 8) {
6109                         navail = 8;
6110                 } else if ((navail & 4) == 4) {
6111                         navail = 4;
6112                 } else if ((navail & 2) == 2) {
6113                         navail = 2;
6114                 } else {
6115                         navail = 1;
6116                 }
6117                 NXGE_DEBUG_MSG((nxgep, INT_CTL,
6118                     "ddi_intr_get_navail(): (msi power of 2) nintrs %d, "
6119                     "navail %d", nintrs, navail));
6120         }
6121 
6122         behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
6123             DDI_INTR_ALLOC_NORMAL);
6124         intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
6125         intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
6126         ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
6127             navail, &nactual, behavior);
6128         if (ddi_status != DDI_SUCCESS || nactual == 0) {
6129                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6130                     " ddi_intr_alloc() failed: %d",
6131                     ddi_status));
6132                 kmem_free(intrp->htable, intrp->intr_size);
6133                 return (NXGE_ERROR | NXGE_DDI_FAILED);
6134         }
6135 
6136         if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
6137             (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
6138                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6139                     " ddi_intr_get_pri() failed: %d",
6140                     ddi_status));
6141                 /* Free already allocated interrupts */
6142                 for (y = 0; y < nactual; y++) {
6143                         (void) ddi_intr_free(intrp->htable[y]);
6144                 }
6145 
6146                 kmem_free(intrp->htable, intrp->intr_size);
6147                 return (NXGE_ERROR | NXGE_DDI_FAILED);
6148         }
6149 
6150         nrequired = 0;
6151         switch (nxgep->niu_type) {
6152         default:
6153                 status = nxge_ldgv_init(nxgep, &nactual, &nrequired);
6154                 break;
6155 
6156         case N2_NIU:
6157                 status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired);
6158                 break;
6159         }
6160 
6161         if (status != NXGE_OK) {
6162                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6163                     "nxge_add_intrs_adv_typ:nxge_ldgv_init "
6164                     "failed: 0x%x", status));
6165                 /* Free already allocated interrupts */
6166                 for (y = 0; y < nactual; y++) {
6167                         (void) ddi_intr_free(intrp->htable[y]);
6168                 }
6169 
6170                 kmem_free(intrp->htable, intrp->intr_size);
6171                 return (status);
6172         }
6173 
6174         ldgp = nxgep->ldgvp->ldgp;
6175         for (x = 0; x < nrequired; x++, ldgp++) {
6176                 ldgp->vector = (uint8_t)x;
6177                 ldgp->intdata = SID_DATA(ldgp->func, x);
6178                 arg1 = ldgp->ldvp;
6179                 arg2 = nxgep;
6180                 if (ldgp->nldvs == 1) {
6181                         inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
6182                         NXGE_DEBUG_MSG((nxgep, INT_CTL,
6183                             "nxge_add_intrs_adv_type: "
6184                             "arg1 0x%x arg2 0x%x: "
6185                             "1-1 int handler (entry %d intdata 0x%x)\n",
6186                             arg1, arg2,
6187                             x, ldgp->intdata));
6188                 } else if (ldgp->nldvs > 1) {
6189                         inthandler = (uint_t *)ldgp->sys_intr_handler;
6190                         NXGE_DEBUG_MSG((nxgep, INT_CTL,
6191                             "nxge_add_intrs_adv_type: "
6192                             "arg1 0x%x arg2 0x%x: "
6193                             "nldevs %d int handler "
6194                             "(entry %d intdata 0x%x)\n",
6195                             arg1, arg2,
6196                             ldgp->nldvs, x, ldgp->intdata));
6197                 }
6198 
6199                 NXGE_DEBUG_MSG((nxgep, INT_CTL,
6200                     "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d "
6201                     "htable 0x%llx", x, intrp->htable[x]));
6202 
6203                 if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
6204                     (ddi_intr_handler_t *)inthandler, arg1, arg2))
6205                     != DDI_SUCCESS) {
6206                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6207                             "==> nxge_add_intrs_adv_type: failed #%d "
6208                             "status 0x%x", x, ddi_status));
6209                         for (y = 0; y < intrp->intr_added; y++) {
6210                                 (void) ddi_intr_remove_handler(
6211                                     intrp->htable[y]);
6212                         }
6213                         /* Free already allocated intr */
6214                         for (y = 0; y < nactual; y++) {
6215                                 (void) ddi_intr_free(intrp->htable[y]);
6216                         }
6217                         kmem_free(intrp->htable, intrp->intr_size);
6218 
6219                         (void) nxge_ldgv_uninit(nxgep);
6220 
6221                         return (NXGE_ERROR | NXGE_DDI_FAILED);
6222                 }
6223 
6224                 ldgp->htable_idx = x;
6225                 intrp->intr_added++;
6226         }
6227 
6228         intrp->msi_intx_cnt = nactual;
6229 
6230         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
6231             "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d",
6232             navail, nactual,
6233             intrp->msi_intx_cnt,
6234             intrp->intr_added));
6235 
6236         (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
6237 
6238         (void) nxge_intr_ldgv_init(nxgep);
6239 
6240         NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type"));
6241 
6242         return (status);
6243 }
6244 
6245 /*ARGSUSED*/
6246 static nxge_status_t
6247 nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type)
6248 {
6249         dev_info_t              *dip = nxgep->dip;
6250         p_nxge_ldg_t            ldgp;
6251         p_nxge_intr_t           intrp;
6252         uint_t                  *inthandler;
6253         void                    *arg1, *arg2;
6254         int                     behavior;
6255         int                     nintrs, navail;
6256         int                     nactual, nrequired;
6257         int                     inum = 0;
6258         int                     x, y;
6259         int                     ddi_status = DDI_SUCCESS;
6260         nxge_status_t           status = NXGE_OK;
6261 
6262         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix"));
6263         intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6264         intrp->start_inum = 0;
6265 
6266         ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
6267         if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
6268                 NXGE_DEBUG_MSG((nxgep, INT_CTL,
6269                     "ddi_intr_get_nintrs() failed, status: 0x%x%, "
6270                     "nintrs: %d", status, nintrs));
6271                 return (NXGE_ERROR | NXGE_DDI_FAILED);
6272         }
6273 
6274         ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
6275         if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
6276                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6277                     "ddi_intr_get_navail() failed, status: 0x%x%, "
6278                     "nintrs: %d", ddi_status, navail));
6279                 return (NXGE_ERROR | NXGE_DDI_FAILED);
6280         }
6281 
6282         NXGE_DEBUG_MSG((nxgep, INT_CTL,
6283             "ddi_intr_get_navail() returned: nintrs %d, naavail %d",
6284             nintrs, navail));
6285 
6286         behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
6287             DDI_INTR_ALLOC_NORMAL);
6288         intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
6289         intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
6290         ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
6291             navail, &nactual, behavior);
6292         if (ddi_status != DDI_SUCCESS || nactual == 0) {
6293                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6294                     " ddi_intr_alloc() failed: %d",
6295                     ddi_status));
6296                 kmem_free(intrp->htable, intrp->intr_size);
6297                 return (NXGE_ERROR | NXGE_DDI_FAILED);
6298         }
6299 
6300         if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
6301             (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
6302                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6303                     " ddi_intr_get_pri() failed: %d",
6304                     ddi_status));
6305                 /* Free already allocated interrupts */
6306                 for (y = 0; y < nactual; y++) {
6307                         (void) ddi_intr_free(intrp->htable[y]);
6308                 }
6309 
6310                 kmem_free(intrp->htable, intrp->intr_size);
6311                 return (NXGE_ERROR | NXGE_DDI_FAILED);
6312         }
6313 
6314         nrequired = 0;
6315         switch (nxgep->niu_type) {
6316         default:
6317                 status = nxge_ldgv_init(nxgep, &nactual, &nrequired);
6318                 break;
6319 
6320         case N2_NIU:
6321                 status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired);
6322                 break;
6323         }
6324 
6325         if (status != NXGE_OK) {
6326                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6327                     "nxge_add_intrs_adv_type_fix:nxge_ldgv_init "
6328                     "failed: 0x%x", status));
6329                 /* Free already allocated interrupts */
6330                 for (y = 0; y < nactual; y++) {
6331                         (void) ddi_intr_free(intrp->htable[y]);
6332                 }
6333 
6334                 kmem_free(intrp->htable, intrp->intr_size);
6335                 return (status);
6336         }
6337 
6338         ldgp = nxgep->ldgvp->ldgp;
6339         for (x = 0; x < nrequired; x++, ldgp++) {
6340                 ldgp->vector = (uint8_t)x;
6341                 if (nxgep->niu_type != N2_NIU) {
6342                         ldgp->intdata = SID_DATA(ldgp->func, x);
6343                 }
6344 
6345                 arg1 = ldgp->ldvp;
6346                 arg2 = nxgep;
6347                 if (ldgp->nldvs == 1) {
6348                         inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
6349                         NXGE_DEBUG_MSG((nxgep, INT_CTL,
6350                             "nxge_add_intrs_adv_type_fix: "
6351                             "1-1 int handler(%d) ldg %d ldv %d "
6352                             "arg1 $%p arg2 $%p\n",
6353                             x, ldgp->ldg, ldgp->ldvp->ldv,
6354                             arg1, arg2));
6355                 } else if (ldgp->nldvs > 1) {
6356                         inthandler = (uint_t *)ldgp->sys_intr_handler;
6357                         NXGE_DEBUG_MSG((nxgep, INT_CTL,
6358                             "nxge_add_intrs_adv_type_fix: "
6359                             "shared ldv %d int handler(%d) ldv %d ldg %d"
6360                             "arg1 0x%016llx arg2 0x%016llx\n",
6361                             x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv,
6362                             arg1, arg2));
6363                 }
6364 
6365                 if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
6366                     (ddi_intr_handler_t *)inthandler, arg1, arg2))
6367                     != DDI_SUCCESS) {
6368                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6369                             "==> nxge_add_intrs_adv_type_fix: failed #%d "
6370                             "status 0x%x", x, ddi_status));
6371                         for (y = 0; y < intrp->intr_added; y++) {
6372                                 (void) ddi_intr_remove_handler(
6373                                     intrp->htable[y]);
6374                         }
6375                         for (y = 0; y < nactual; y++) {
6376                                 (void) ddi_intr_free(intrp->htable[y]);
6377                         }
6378                         /* Free already allocated intr */
6379                         kmem_free(intrp->htable, intrp->intr_size);
6380 
6381                         (void) nxge_ldgv_uninit(nxgep);
6382 
6383                         return (NXGE_ERROR | NXGE_DDI_FAILED);
6384                 }
6385 
6386                 ldgp->htable_idx = x;
6387                 intrp->intr_added++;
6388         }
6389 
6390         intrp->msi_intx_cnt = nactual;
6391 
6392         (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
6393 
6394         status = nxge_intr_ldgv_init(nxgep);
6395         NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix"));
6396 
6397         return (status);
6398 }
6399 
6400 static void
6401 nxge_remove_intrs(p_nxge_t nxgep)
6402 {
6403         int             i, inum;
6404         p_nxge_intr_t   intrp;
6405 
6406         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs"));
6407         intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6408         if (!intrp->intr_registered) {
6409                 NXGE_DEBUG_MSG((nxgep, INT_CTL,
6410                     "<== nxge_remove_intrs: interrupts not registered"));
6411                 return;
6412         }
6413 
6414         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced"));
6415 
6416         if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
6417                 (void) ddi_intr_block_disable(intrp->htable,
6418                     intrp->intr_added);
6419         } else {
6420                 for (i = 0; i < intrp->intr_added; i++) {
6421                         (void) ddi_intr_disable(intrp->htable[i]);
6422                 }
6423         }
6424 
6425         for (inum = 0; inum < intrp->intr_added; inum++) {
6426                 if (intrp->htable[inum]) {
6427                         (void) ddi_intr_remove_handler(intrp->htable[inum]);
6428                 }
6429         }
6430 
6431         for (inum = 0; inum < intrp->msi_intx_cnt; inum++) {
6432                 if (intrp->htable[inum]) {
6433                         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
6434                             "nxge_remove_intrs: ddi_intr_free inum %d "
6435                             "msi_intx_cnt %d intr_added %d",
6436                             inum,
6437                             intrp->msi_intx_cnt,
6438                             intrp->intr_added));
6439 
6440                         (void) ddi_intr_free(intrp->htable[inum]);
6441                 }
6442         }
6443 
6444         kmem_free(intrp->htable, intrp->intr_size);
6445         intrp->intr_registered = B_FALSE;
6446         intrp->intr_enabled = B_FALSE;
6447         intrp->msi_intx_cnt = 0;
6448         intrp->intr_added = 0;
6449 
6450         (void) nxge_ldgv_uninit(nxgep);
6451 
6452         (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip,
6453             "#msix-request");
6454 
6455         NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs"));
6456 }
6457 
6458 /*ARGSUSED*/
6459 static void
6460 nxge_intrs_enable(p_nxge_t nxgep)
6461 {
6462         p_nxge_intr_t   intrp;
6463         int             i;
6464         int             status;
6465 
6466         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable"));
6467 
6468         intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6469 
6470         if (!intrp->intr_registered) {
6471                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: "
6472                     "interrupts are not registered"));
6473                 return;
6474         }
6475 
6476         if (intrp->intr_enabled) {
6477                 NXGE_DEBUG_MSG((nxgep, INT_CTL,
6478                     "<== nxge_intrs_enable: already enabled"));
6479                 return;
6480         }
6481 
6482         if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
6483                 status = ddi_intr_block_enable(intrp->htable,
6484                     intrp->intr_added);
6485                 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable "
6486                     "block enable - status 0x%x total inums #%d\n",
6487                     status, intrp->intr_added));
6488         } else {
6489                 for (i = 0; i < intrp->intr_added; i++) {
6490                         status = ddi_intr_enable(intrp->htable[i]);
6491                         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable "
6492                             "ddi_intr_enable:enable - status 0x%x "
6493                             "total inums %d enable inum #%d\n",
6494                             status, intrp->intr_added, i));
6495                         if (status == DDI_SUCCESS) {
6496                                 intrp->intr_enabled = B_TRUE;
6497                         }
6498                 }
6499         }
6500 
6501         NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable"));
6502 }
6503 
6504 /*ARGSUSED*/
6505 static void
6506 nxge_intrs_disable(p_nxge_t nxgep)
6507 {
6508         p_nxge_intr_t   intrp;
6509         int             i;
6510 
6511         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable"));
6512 
6513         intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6514 
6515         if (!intrp->intr_registered) {
6516                 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: "
6517                     "interrupts are not registered"));
6518                 return;
6519         }
6520 
6521         if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
6522                 (void) ddi_intr_block_disable(intrp->htable,
6523                     intrp->intr_added);
6524         } else {
6525                 for (i = 0; i < intrp->intr_added; i++) {
6526                         (void) ddi_intr_disable(intrp->htable[i]);
6527                 }
6528         }
6529 
6530         intrp->intr_enabled = B_FALSE;
6531         NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable"));
6532 }
6533 
6534 nxge_status_t
6535 nxge_mac_register(p_nxge_t nxgep)
6536 {
6537         mac_register_t *macp;
6538         int             status;
6539 
6540         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register"));
6541 
6542         if ((macp = mac_alloc(MAC_VERSION)) == NULL)
6543                 return (NXGE_ERROR);
6544 
6545         macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
6546         macp->m_driver = nxgep;
6547         macp->m_dip = nxgep->dip;
6548         if (!isLDOMguest(nxgep)) {
6549                 macp->m_src_addr = nxgep->ouraddr.ether_addr_octet;
6550         } else {
6551                 macp->m_src_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP);
6552                 macp->m_dst_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP);
6553                 (void) memset(macp->m_src_addr, 0xff, sizeof (MAXMACADDRLEN));
6554         }
6555         macp->m_callbacks = &nxge_m_callbacks;
6556         macp->m_min_sdu = 0;
6557         nxgep->mac.default_mtu = nxgep->mac.maxframesize -
6558             NXGE_EHEADER_VLAN_CRC;
6559         macp->m_max_sdu = nxgep->mac.default_mtu;
6560         macp->m_margin = VLAN_TAGSZ;
6561         macp->m_priv_props = nxge_priv_props;
6562         if (isLDOMguest(nxgep))
6563                 macp->m_v12n = MAC_VIRT_LEVEL1;
6564         else
6565                 macp->m_v12n = MAC_VIRT_HIO | MAC_VIRT_LEVEL1;
6566 
6567         NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6568             "==> nxge_mac_register: instance %d "
6569             "max_sdu %d margin %d maxframe %d (header %d)",
6570             nxgep->instance,
6571             macp->m_max_sdu, macp->m_margin,
6572             nxgep->mac.maxframesize,
6573             NXGE_EHEADER_VLAN_CRC));
6574 
6575         status = mac_register(macp, &nxgep->mach);
6576         if (isLDOMguest(nxgep)) {
6577                 KMEM_FREE(macp->m_src_addr, MAXMACADDRLEN);
6578                 KMEM_FREE(macp->m_dst_addr, MAXMACADDRLEN);
6579         }
6580         mac_free(macp);
6581 
6582         if (status != 0) {
6583                 cmn_err(CE_WARN,
6584                     "!nxge_mac_register failed (status %d instance %d)",
6585                     status, nxgep->instance);
6586                 return (NXGE_ERROR);
6587         }
6588 
6589         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success "
6590             "(instance %d)", nxgep->instance));
6591 
6592         return (NXGE_OK);
6593 }
6594 
6595 void
6596 nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp)
6597 {
6598         ssize_t         size;
6599         mblk_t          *nmp;
6600         uint8_t         blk_id;
6601         uint8_t         chan;
6602         uint32_t        err_id;
6603         err_inject_t    *eip;
6604 
6605         NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject"));
6606 
6607         size = 1024;
6608         nmp = mp->b_cont;
6609         eip = (err_inject_t *)nmp->b_rptr;
6610         blk_id = eip->blk_id;
6611         err_id = eip->err_id;
6612         chan = eip->chan;
6613         cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id);
6614         cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id);
6615         cmn_err(CE_NOTE, "!chan = 0x%x\n", chan);
6616         switch (blk_id) {
6617         case MAC_BLK_ID:
6618                 break;
6619         case TXMAC_BLK_ID:
6620                 break;
6621         case RXMAC_BLK_ID:
6622                 break;
6623         case MIF_BLK_ID:
6624                 break;
6625         case IPP_BLK_ID:
6626                 nxge_ipp_inject_err(nxgep, err_id);
6627                 break;
6628         case TXC_BLK_ID:
6629                 nxge_txc_inject_err(nxgep, err_id);
6630                 break;
6631         case TXDMA_BLK_ID:
6632                 nxge_txdma_inject_err(nxgep, err_id, chan);
6633                 break;
6634         case RXDMA_BLK_ID:
6635                 nxge_rxdma_inject_err(nxgep, err_id, chan);
6636                 break;
6637         case ZCP_BLK_ID:
6638                 nxge_zcp_inject_err(nxgep, err_id);
6639                 break;
6640         case ESPC_BLK_ID:
6641                 break;
6642         case FFLP_BLK_ID:
6643                 break;
6644         case PHY_BLK_ID:
6645                 break;
6646         case ETHER_SERDES_BLK_ID:
6647                 break;
6648         case PCIE_SERDES_BLK_ID:
6649                 break;
6650         case VIR_BLK_ID:
6651                 break;
6652         }
6653 
6654         nmp->b_wptr = nmp->b_rptr + size;
6655         NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject"));
6656 
6657         miocack(wq, mp, (int)size, 0);
6658 }
6659 
6660 static int
6661 nxge_init_common_dev(p_nxge_t nxgep)
6662 {
6663         p_nxge_hw_list_t        hw_p;
6664         dev_info_t              *p_dip;
6665 
6666         ASSERT(nxgep != NULL);
6667 
6668         NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device"));
6669 
6670         p_dip = nxgep->p_dip;
6671         MUTEX_ENTER(&nxge_common_lock);
6672         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6673             "==> nxge_init_common_dev:func # %d",
6674             nxgep->function_num));
6675         /*
6676          * Loop through existing per neptune hardware list.
6677          */
6678         for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) {
6679                 NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6680                     "==> nxge_init_common_device:func # %d "
6681                     "hw_p $%p parent dip $%p",
6682                     nxgep->function_num,
6683                     hw_p,
6684                     p_dip));
6685                 if (hw_p->parent_devp == p_dip) {
6686                         nxgep->nxge_hw_p = hw_p;
6687                         hw_p->ndevs++;
6688                         hw_p->nxge_p[nxgep->function_num] = nxgep;
6689                         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6690                             "==> nxge_init_common_device:func # %d "
6691                             "hw_p $%p parent dip $%p "
6692                             "ndevs %d (found)",
6693                             nxgep->function_num,
6694                             hw_p,
6695                             p_dip,
6696                             hw_p->ndevs));
6697                         break;
6698                 }
6699         }
6700 
6701         if (hw_p == NULL) {
6702 
6703                 char **prop_val;
6704                 uint_t prop_len;
6705                 int i;
6706 
6707                 NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6708                     "==> nxge_init_common_device:func # %d "
6709                     "parent dip $%p (new)",
6710                     nxgep->function_num,
6711                     p_dip));
6712                 hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP);
6713                 hw_p->parent_devp = p_dip;
6714                 hw_p->magic = NXGE_NEPTUNE_MAGIC;
6715                 nxgep->nxge_hw_p = hw_p;
6716                 hw_p->ndevs++;
6717                 hw_p->nxge_p[nxgep->function_num] = nxgep;
6718                 hw_p->next = nxge_hw_list;
6719                 if (nxgep->niu_type == N2_NIU) {
6720                         hw_p->niu_type = N2_NIU;
6721                         hw_p->platform_type = P_NEPTUNE_NIU;
6722                         hw_p->tcam_size = TCAM_NIU_TCAM_MAX_ENTRY;
6723                 } else {
6724                         hw_p->niu_type = NIU_TYPE_NONE;
6725                         hw_p->platform_type = P_NEPTUNE_NONE;
6726                         hw_p->tcam_size = TCAM_NXGE_TCAM_MAX_ENTRY;
6727                 }
6728 
6729                 hw_p->tcam = KMEM_ZALLOC(sizeof (tcam_flow_spec_t) *
6730                     hw_p->tcam_size, KM_SLEEP);
6731 
6732                 MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL);
6733                 MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL);
6734                 MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL);
6735                 MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL);
6736 
6737                 nxge_hw_list = hw_p;
6738 
6739                 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, nxgep->dip, 0,
6740                     "compatible", &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
6741                         for (i = 0; i < prop_len; i++) {
6742                                 if ((strcmp((caddr_t)prop_val[i],
6743                                     NXGE_ROCK_COMPATIBLE) == 0)) {
6744                                         hw_p->platform_type = P_NEPTUNE_ROCK;
6745                                         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6746                                             "ROCK hw_p->platform_type %d",
6747                                             hw_p->platform_type));
6748                                         break;
6749                                 }
6750                                 NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6751                                     "nxge_init_common_dev: read compatible"
6752                                     " property[%d] val[%s]",
6753                                     i, (caddr_t)prop_val[i]));
6754                         }
6755                 }
6756 
6757                 ddi_prop_free(prop_val);
6758 
6759                 (void) nxge_scan_ports_phy(nxgep, nxge_hw_list);
6760         }
6761 
6762         MUTEX_EXIT(&nxge_common_lock);
6763 
6764         nxgep->platform_type = hw_p->platform_type;
6765         NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxgep->platform_type %d",
6766             nxgep->platform_type));
6767         if (nxgep->niu_type != N2_NIU) {
6768                 nxgep->niu_type = hw_p->niu_type;
6769         }
6770 
6771         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6772             "==> nxge_init_common_device (nxge_hw_list) $%p",
6773             nxge_hw_list));
6774         NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device"));
6775 
6776         return (NXGE_OK);
6777 }
6778 
6779 static void
6780 nxge_uninit_common_dev(p_nxge_t nxgep)
6781 {
6782         p_nxge_hw_list_t        hw_p, h_hw_p;
6783         p_nxge_dma_pt_cfg_t     p_dma_cfgp;
6784         p_nxge_hw_pt_cfg_t      p_cfgp;
6785         dev_info_t              *p_dip;
6786 
6787         ASSERT(nxgep != NULL);
6788 
6789         NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device"));
6790         if (nxgep->nxge_hw_p == NULL) {
6791                 NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6792                     "<== nxge_uninit_common_device (no common)"));
6793                 return;
6794         }
6795 
6796         MUTEX_ENTER(&nxge_common_lock);
6797         h_hw_p = nxge_hw_list;
6798         for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) {
6799                 p_dip = hw_p->parent_devp;
6800                 if (nxgep->nxge_hw_p == hw_p &&
6801                     p_dip == nxgep->p_dip &&
6802                     nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC &&
6803                     hw_p->magic == NXGE_NEPTUNE_MAGIC) {
6804 
6805                         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6806                             "==> nxge_uninit_common_device:func # %d "
6807                             "hw_p $%p parent dip $%p "
6808                             "ndevs %d (found)",
6809                             nxgep->function_num,
6810                             hw_p,
6811                             p_dip,
6812                             hw_p->ndevs));
6813 
6814                         /*
6815                          * Release the RDC table, a shared resoruce
6816                          * of the nxge hardware.  The RDC table was
6817                          * assigned to this instance of nxge in
6818                          * nxge_use_cfg_dma_config().
6819                          */
6820                         if (!isLDOMguest(nxgep)) {
6821                                 p_dma_cfgp =
6822                                     (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
6823                                 p_cfgp =
6824                                     (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
6825                                 (void) nxge_fzc_rdc_tbl_unbind(nxgep,
6826                                     p_cfgp->def_mac_rxdma_grpid);
6827 
6828                                 /* Cleanup any outstanding groups.  */
6829                                 nxge_grp_cleanup(nxgep);
6830                         }
6831 
6832                         if (hw_p->ndevs) {
6833                                 hw_p->ndevs--;
6834                         }
6835                         hw_p->nxge_p[nxgep->function_num] = NULL;
6836                         if (!hw_p->ndevs) {
6837                                 KMEM_FREE(hw_p->tcam,
6838                                     sizeof (tcam_flow_spec_t) *
6839                                     hw_p->tcam_size);
6840                                 MUTEX_DESTROY(&hw_p->nxge_vlan_lock);
6841                                 MUTEX_DESTROY(&hw_p->nxge_tcam_lock);
6842                                 MUTEX_DESTROY(&hw_p->nxge_cfg_lock);
6843                                 MUTEX_DESTROY(&hw_p->nxge_mdio_lock);
6844                                 NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6845                                     "==> nxge_uninit_common_device: "
6846                                     "func # %d "
6847                                     "hw_p $%p parent dip $%p "
6848                                     "ndevs %d (last)",
6849                                     nxgep->function_num,
6850                                     hw_p,
6851                                     p_dip,
6852                                     hw_p->ndevs));
6853 
6854                                 nxge_hio_uninit(nxgep);
6855 
6856                                 if (hw_p == nxge_hw_list) {
6857                                         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6858                                             "==> nxge_uninit_common_device:"
6859                                             "remove head func # %d "
6860                                             "hw_p $%p parent dip $%p "
6861                                             "ndevs %d (head)",
6862                                             nxgep->function_num,
6863                                             hw_p,
6864                                             p_dip,
6865                                             hw_p->ndevs));
6866                                         nxge_hw_list = hw_p->next;
6867                                 } else {
6868                                         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6869                                             "==> nxge_uninit_common_device:"
6870                                             "remove middle func # %d "
6871                                             "hw_p $%p parent dip $%p "
6872                                             "ndevs %d (middle)",
6873                                             nxgep->function_num,
6874                                             hw_p,
6875                                             p_dip,
6876                                             hw_p->ndevs));
6877                                         h_hw_p->next = hw_p->next;
6878                                 }
6879 
6880                                 nxgep->nxge_hw_p = NULL;
6881                                 KMEM_FREE(hw_p, sizeof (nxge_hw_list_t));
6882                         }
6883                         break;
6884                 } else {
6885                         h_hw_p = hw_p;
6886                 }
6887         }
6888 
6889         MUTEX_EXIT(&nxge_common_lock);
6890         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6891             "==> nxge_uninit_common_device (nxge_hw_list) $%p",
6892             nxge_hw_list));
6893 
6894         NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device"));
6895 }
6896 
6897 /*
6898  * Determines the number of ports from the niu_type or the platform type.
6899  * Returns the number of ports, or returns zero on failure.
6900  */
6901 
6902 int
6903 nxge_get_nports(p_nxge_t nxgep)
6904 {
6905         int     nports = 0;
6906 
6907         switch (nxgep->niu_type) {
6908         case N2_NIU:
6909         case NEPTUNE_2_10GF:
6910                 nports = 2;
6911                 break;
6912         case NEPTUNE_4_1GC:
6913         case NEPTUNE_2_10GF_2_1GC:
6914         case NEPTUNE_1_10GF_3_1GC:
6915         case NEPTUNE_1_1GC_1_10GF_2_1GC:
6916         case NEPTUNE_2_10GF_2_1GRF:
6917                 nports = 4;
6918                 break;
6919         default:
6920                 switch (nxgep->platform_type) {
6921                 case P_NEPTUNE_NIU:
6922                 case P_NEPTUNE_ATLAS_2PORT:
6923                         nports = 2;
6924                         break;
6925                 case P_NEPTUNE_ATLAS_4PORT:
6926                 case P_NEPTUNE_MARAMBA_P0:
6927                 case P_NEPTUNE_MARAMBA_P1:
6928                 case P_NEPTUNE_ROCK:
6929                 case P_NEPTUNE_ALONSO:
6930                         nports = 4;
6931                         break;
6932                 default:
6933                         break;
6934                 }
6935                 break;
6936         }
6937 
6938         return (nports);
6939 }
6940 
6941 /*
6942  * The following two functions are to support
6943  * PSARC/2007/453 MSI-X interrupt limit override.
6944  */
6945 static int
6946 nxge_create_msi_property(p_nxge_t nxgep)
6947 {
6948         int     nmsi;
6949         extern  int ncpus;
6950 
6951         NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property"));
6952 
6953         switch (nxgep->mac.portmode) {
6954         case PORT_10G_COPPER:
6955         case PORT_10G_FIBER:
6956         case PORT_10G_TN1010:
6957                 (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip,
6958                     DDI_PROP_CANSLEEP, "#msix-request", NULL, 0);
6959                 /*
6960                  * The maximum MSI-X requested will be 8.
6961                  * If the # of CPUs is less than 8, we will request
6962                  * # MSI-X based on the # of CPUs (default).
6963                  */
6964                 NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6965                     "==>nxge_create_msi_property (10G): nxge_msix_10g_intrs %d",
6966                     nxge_msix_10g_intrs));
6967                 if ((nxge_msix_10g_intrs == 0) ||
6968                     (nxge_msix_10g_intrs > NXGE_MSIX_MAX_ALLOWED)) {
6969                         nmsi = NXGE_MSIX_REQUEST_10G;
6970                         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6971                             "==>nxge_create_msi_property (10G): reset to 8"));
6972                 } else {
6973                         nmsi = nxge_msix_10g_intrs;
6974                 }
6975 
6976                 /*
6977                  * If # of interrupts requested is 8 (default),
6978                  * the checking of the number of cpus will be
6979                  * be maintained.
6980                  */
6981                 if ((nmsi == NXGE_MSIX_REQUEST_10G) &&
6982                     (ncpus < nmsi)) {
6983                         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6984                             "==>nxge_create_msi_property (10G): reset to 8"));
6985                         nmsi = ncpus;
6986                 }
6987                 NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6988                     "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)",
6989                     ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip,
6990                     DDI_PROP_CANSLEEP, "#msix-request"), nmsi));
6991                 break;
6992 
6993         default:
6994                 (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip,
6995                     DDI_PROP_CANSLEEP, "#msix-request", NULL, 0);
6996                 NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6997                     "==>nxge_create_msi_property (1G): nxge_msix_1g_intrs %d",
6998                     nxge_msix_1g_intrs));
6999                 if ((nxge_msix_1g_intrs == 0) ||
7000                     (nxge_msix_1g_intrs > NXGE_MSIX_MAX_ALLOWED)) {
7001                         nmsi = NXGE_MSIX_REQUEST_1G;
7002                         NXGE_DEBUG_MSG((nxgep, MOD_CTL,
7003                             "==>nxge_create_msi_property (1G): reset to 2"));
7004                 } else {
7005                         nmsi = nxge_msix_1g_intrs;
7006                 }
7007                 NXGE_DEBUG_MSG((nxgep, MOD_CTL,
7008                     "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)",
7009                     ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip,
7010                     DDI_PROP_CANSLEEP, "#msix-request"), nmsi));
7011                 break;
7012         }
7013 
7014         NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property"));
7015         return (nmsi);
7016 }
7017 
7018 /*
7019  * The following is a software around for the Neptune hardware's
7020  * interrupt bugs; The Neptune hardware may generate spurious interrupts when
7021  * an interrupr handler is removed.
7022  */
7023 #define NXGE_PCI_PORT_LOGIC_OFFSET      0x98
7024 #define NXGE_PIM_RESET                  (1ULL << 29)
7025 #define NXGE_GLU_RESET                  (1ULL << 30)
7026 #define NXGE_NIU_RESET                  (1ULL << 31)
7027 #define NXGE_PCI_RESET_ALL              (NXGE_PIM_RESET |       \
7028                                         NXGE_GLU_RESET |        \
7029                                         NXGE_NIU_RESET)
7030 
7031 #define NXGE_WAIT_QUITE_TIME            200000
7032 #define NXGE_WAIT_QUITE_RETRY           40
7033 #define NXGE_PCI_RESET_WAIT             1000000 /* one second */
7034 
7035 static void
7036 nxge_niu_peu_reset(p_nxge_t nxgep)
7037 {
7038         uint32_t        rvalue;
7039         p_nxge_hw_list_t hw_p;
7040         p_nxge_t        fnxgep;
7041         int             i, j;
7042 
7043         NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_niu_peu_reset"));
7044         if ((hw_p = nxgep->nxge_hw_p) == NULL) {
7045                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7046                     "==> nxge_niu_peu_reset: NULL hardware pointer"));
7047                 return;
7048         }
7049 
7050         NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7051             "==> nxge_niu_peu_reset: flags 0x%x link timer id %d timer id %d",
7052             hw_p->flags, nxgep->nxge_link_poll_timerid,
7053             nxgep->nxge_timerid));
7054 
7055         MUTEX_ENTER(&hw_p->nxge_cfg_lock);
7056         /*
7057          * Make sure other instances from the same hardware
7058          * stop sending PIO and in quiescent state.
7059          */
7060         for (i = 0; i < NXGE_MAX_PORTS; i++) {
7061                 fnxgep = hw_p->nxge_p[i];
7062                 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7063                     "==> nxge_niu_peu_reset: checking entry %d "
7064                     "nxgep $%p", i, fnxgep));
7065 #ifdef  NXGE_DEBUG
7066                 if (fnxgep) {
7067                         NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7068                             "==> nxge_niu_peu_reset: entry %d (function %d) "
7069                             "link timer id %d hw timer id %d",
7070                             i, fnxgep->function_num,
7071                             fnxgep->nxge_link_poll_timerid,
7072                             fnxgep->nxge_timerid));
7073                 }
7074 #endif
7075                 if (fnxgep && fnxgep != nxgep &&
7076                     (fnxgep->nxge_timerid || fnxgep->nxge_link_poll_timerid)) {
7077                         NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7078                             "==> nxge_niu_peu_reset: checking $%p "
7079                             "(function %d) timer ids",
7080                             fnxgep, fnxgep->function_num));
7081                         for (j = 0; j < NXGE_WAIT_QUITE_RETRY; j++) {
7082                                 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7083                                     "==> nxge_niu_peu_reset: waiting"));
7084                                 NXGE_DELAY(NXGE_WAIT_QUITE_TIME);
7085                                 if (!fnxgep->nxge_timerid &&
7086                                     !fnxgep->nxge_link_poll_timerid) {
7087                                         break;
7088                                 }
7089                         }
7090                         NXGE_DELAY(NXGE_WAIT_QUITE_TIME);
7091                         if (fnxgep->nxge_timerid ||
7092                             fnxgep->nxge_link_poll_timerid) {
7093                                 MUTEX_EXIT(&hw_p->nxge_cfg_lock);
7094                                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7095                                     "<== nxge_niu_peu_reset: cannot reset "
7096                                     "hardware (devices are still in use)"));
7097                                 return;
7098                         }
7099                 }
7100         }
7101 
7102         if ((hw_p->flags & COMMON_RESET_NIU_PCI) != COMMON_RESET_NIU_PCI) {
7103                 hw_p->flags |= COMMON_RESET_NIU_PCI;
7104                 rvalue = pci_config_get32(nxgep->dev_regs->nxge_pciregh,
7105                     NXGE_PCI_PORT_LOGIC_OFFSET);
7106                 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7107                     "nxge_niu_peu_reset: read offset 0x%x (%d) "
7108                     "(data 0x%x)",
7109                     NXGE_PCI_PORT_LOGIC_OFFSET,
7110                     NXGE_PCI_PORT_LOGIC_OFFSET,
7111                     rvalue));
7112 
7113                 rvalue |= NXGE_PCI_RESET_ALL;
7114                 pci_config_put32(nxgep->dev_regs->nxge_pciregh,
7115                     NXGE_PCI_PORT_LOGIC_OFFSET, rvalue);
7116                 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7117                     "nxge_niu_peu_reset: RESETTING NIU: write NIU reset 0x%x",
7118                     rvalue));
7119 
7120                 NXGE_DELAY(NXGE_PCI_RESET_WAIT);
7121         }
7122 
7123         MUTEX_EXIT(&hw_p->nxge_cfg_lock);
7124         NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_niu_peu_reset"));
7125 }
7126 
7127 static void
7128 nxge_set_pci_replay_timeout(p_nxge_t nxgep)
7129 {
7130         p_dev_regs_t    dev_regs;
7131         uint32_t        value;
7132 
7133         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_pci_replay_timeout"));
7134 
7135         if (!nxge_set_replay_timer) {
7136                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
7137                     "==> nxge_set_pci_replay_timeout: will not change "
7138                     "the timeout"));
7139                 return;
7140         }
7141 
7142         dev_regs = nxgep->dev_regs;
7143         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
7144             "==> nxge_set_pci_replay_timeout: dev_regs 0x%p pcireg 0x%p",
7145             dev_regs, dev_regs->nxge_pciregh));
7146 
7147         if (dev_regs == NULL || (dev_regs->nxge_pciregh == NULL)) {
7148                 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
7149                     "==> nxge_set_pci_replay_timeout: NULL dev_regs $%p or "
7150                     "no PCI handle",
7151                     dev_regs));
7152                 return;
7153         }
7154         value = (pci_config_get32(dev_regs->nxge_pciregh,
7155             PCI_REPLAY_TIMEOUT_CFG_OFFSET) |
7156             (nxge_replay_timeout << PCI_REPLAY_TIMEOUT_SHIFT));
7157 
7158         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
7159             "nxge_set_pci_replay_timeout: replay timeout value before set 0x%x "
7160             "(timeout value to set 0x%x at offset 0x%x) value 0x%x",
7161             pci_config_get32(dev_regs->nxge_pciregh,
7162             PCI_REPLAY_TIMEOUT_CFG_OFFSET), nxge_replay_timeout,
7163             PCI_REPLAY_TIMEOUT_CFG_OFFSET, value));
7164 
7165         pci_config_put32(dev_regs->nxge_pciregh, PCI_REPLAY_TIMEOUT_CFG_OFFSET,
7166             value);
7167 
7168         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
7169             "nxge_set_pci_replay_timeout: replay timeout value after set 0x%x",
7170             pci_config_get32(dev_regs->nxge_pciregh,
7171             PCI_REPLAY_TIMEOUT_CFG_OFFSET)));
7172 
7173         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_pci_replay_timeout"));
7174 }
7175 
7176 /*
7177  * quiesce(9E) entry point.
7178  *
7179  * This function is called when the system is single-threaded at high
7180  * PIL with preemption disabled. Therefore, this function must not be
7181  * blocked.
7182  *
7183  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
7184  * DDI_FAILURE indicates an error condition and should almost never happen.
7185  */
7186 static int
7187 nxge_quiesce(dev_info_t *dip)
7188 {
7189         int instance = ddi_get_instance(dip);
7190         p_nxge_t nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
7191 
7192         if (nxgep == NULL)
7193                 return (DDI_FAILURE);
7194 
7195         /* Turn off debugging */
7196         nxge_debug_level = NO_DEBUG;
7197         nxgep->nxge_debug_level = NO_DEBUG;
7198         npi_debug_level = NO_DEBUG;
7199 
7200         /*
7201          * Stop link monitor only when linkchkmod is interrupt based
7202          */
7203         if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
7204                 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
7205         }
7206 
7207         (void) nxge_intr_hw_disable(nxgep);
7208 
7209         /*
7210          * Reset the receive MAC side.
7211          */
7212         (void) nxge_rx_mac_disable(nxgep);
7213 
7214         /* Disable and soft reset the IPP */
7215         if (!isLDOMguest(nxgep))
7216                 (void) nxge_ipp_disable(nxgep);
7217 
7218         /*
7219          * Reset the transmit/receive DMA side.
7220          */
7221         (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
7222         (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
7223 
7224         /*
7225          * Reset the transmit MAC side.
7226          */
7227         (void) nxge_tx_mac_disable(nxgep);
7228 
7229         return (DDI_SUCCESS);
7230 }