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