Home | History | Annotate | Download | only in nge
      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 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 
     28 #include "nge.h"
     29 
     30 /*
     31  * Describes the chip's DMA engine
     32  */
     33 
     34 static ddi_dma_attr_t hot_dma_attr = {
     35 	DMA_ATTR_V0,			/* dma_attr version	*/
     36 	0x0000000000000000ull,		/* dma_attr_addr_lo	*/
     37 	0x000000FFFFFFFFFFull,		/* dma_attr_addr_hi	*/
     38 	0x000000007FFFFFFFull,		/* dma_attr_count_max	*/
     39 	0x0000000000000010ull,		/* dma_attr_align	*/
     40 	0x00000FFF,			/* dma_attr_burstsizes	*/
     41 	0x00000001,			/* dma_attr_minxfer	*/
     42 	0x000000000000FFFFull,		/* dma_attr_maxxfer	*/
     43 	0x000000FFFFFFFFFFull,		/* dma_attr_seg		*/
     44 	1,				/* dma_attr_sgllen 	*/
     45 	0x00000001,			/* dma_attr_granular 	*/
     46 	0
     47 };
     48 
     49 static ddi_dma_attr_t hot_tx_dma_attr = {
     50 	DMA_ATTR_V0,			/* dma_attr version	*/
     51 	0x0000000000000000ull,		/* dma_attr_addr_lo	*/
     52 	0x000000FFFFFFFFFFull,		/* dma_attr_addr_hi	*/
     53 	0x0000000000003FFFull,		/* dma_attr_count_max	*/
     54 	0x0000000000000010ull,		/* dma_attr_align	*/
     55 	0x00000FFF,			/* dma_attr_burstsizes	*/
     56 	0x00000001,			/* dma_attr_minxfer	*/
     57 	0x0000000000003FFFull,		/* dma_attr_maxxfer	*/
     58 	0x000000FFFFFFFFFFull,		/* dma_attr_seg		*/
     59 	NGE_MAX_COOKIES,		/* dma_attr_sgllen 	*/
     60 	1,				/* dma_attr_granular 	*/
     61 	0
     62 };
     63 
     64 static ddi_dma_attr_t sum_dma_attr = {
     65 	DMA_ATTR_V0,			/* dma_attr version	*/
     66 	0x0000000000000000ull,		/* dma_attr_addr_lo	*/
     67 	0x00000000FFFFFFFFull,		/* dma_attr_addr_hi	*/
     68 	0x000000007FFFFFFFull,		/* dma_attr_count_max	*/
     69 	0x0000000000000010ull,		/* dma_attr_align	*/
     70 	0x00000FFF,			/* dma_attr_burstsizes	*/
     71 	0x00000001,			/* dma_attr_minxfer	*/
     72 	0x000000000000FFFFull,		/* dma_attr_maxxfer	*/
     73 	0x00000000FFFFFFFFull,		/* dma_attr_seg		*/
     74 	1,				/* dma_attr_sgllen 	*/
     75 	0x00000001,			/* dma_attr_granular 	*/
     76 	0
     77 };
     78 
     79 static ddi_dma_attr_t sum_tx_dma_attr = {
     80 	DMA_ATTR_V0,			/* dma_attr version	*/
     81 	0x0000000000000000ull,		/* dma_attr_addr_lo	*/
     82 	0x00000000FFFFFFFFull,		/* dma_attr_addr_hi	*/
     83 	0x0000000000003FFFull,		/* dma_attr_count_max	*/
     84 	0x0000000000000010ull,		/* dma_attr_align	*/
     85 	0x00000FFF,			/* dma_attr_burstsizes	*/
     86 	0x00000001,			/* dma_attr_minxfer	*/
     87 	0x0000000000003FFFull,		/* dma_attr_maxxfer	*/
     88 	0x00000000FFFFFFFFull,		/* dma_attr_seg		*/
     89 	NGE_MAX_COOKIES,		/* dma_attr_sgllen 	*/
     90 	1,				/* dma_attr_granular 	*/
     91 	0
     92 };
     93 
     94 /*
     95  * DMA access attributes for data.
     96  */
     97 ddi_device_acc_attr_t nge_data_accattr = {
     98 	DDI_DEVICE_ATTR_V0,
     99 	DDI_STRUCTURE_LE_ACC,
    100 	DDI_STRICTORDER_ACC,
    101 	DDI_DEFAULT_ACC
    102 };
    103 
    104 /*
    105  * DMA access attributes for descriptors.
    106  */
    107 static ddi_device_acc_attr_t nge_desc_accattr = {
    108 	DDI_DEVICE_ATTR_V0,
    109 	DDI_STRUCTURE_LE_ACC,
    110 	DDI_STRICTORDER_ACC,
    111 	DDI_DEFAULT_ACC
    112 };
    113 
    114 /*
    115  * PIO access attributes for registers
    116  */
    117 static ddi_device_acc_attr_t nge_reg_accattr = {
    118 	DDI_DEVICE_ATTR_V0,
    119 	DDI_STRUCTURE_LE_ACC,
    120 	DDI_STRICTORDER_ACC,
    121 	DDI_DEFAULT_ACC
    122 };
    123 
    124 /*
    125  * NIC DESC MODE 2
    126  */
    127 
    128 static const nge_desc_attr_t nge_sum_desc = {
    129 
    130 	sizeof (sum_rx_bd),
    131 	sizeof (sum_tx_bd),
    132 	&sum_dma_attr,
    133 	&sum_tx_dma_attr,
    134 	nge_sum_rxd_fill,
    135 	nge_sum_rxd_check,
    136 	nge_sum_txd_fill,
    137 	nge_sum_txd_check,
    138 };
    139 
    140 /*
    141  * NIC DESC MODE 3
    142  */
    143 
    144 static const nge_desc_attr_t nge_hot_desc = {
    145 
    146 	sizeof (hot_rx_bd),
    147 	sizeof (hot_tx_bd),
    148 	&hot_dma_attr,
    149 	&hot_tx_dma_attr,
    150 	nge_hot_rxd_fill,
    151 	nge_hot_rxd_check,
    152 	nge_hot_txd_fill,
    153 	nge_hot_txd_check,
    154 };
    155 
    156 static char nge_ident[] = "nVidia 1Gb Ethernet";
    157 static char clsize_propname[] = "cache-line-size";
    158 static char latency_propname[] = "latency-timer";
    159 static char debug_propname[]	= "nge-debug-flags";
    160 static char intr_moderation[] = "intr-moderation";
    161 static char rx_data_hw[] = "rx-data-hw";
    162 static char rx_prd_lw[] = "rx-prd-lw";
    163 static char rx_prd_hw[] = "rx-prd-hw";
    164 static char sw_intr_intv[] = "sw-intr-intvl";
    165 static char nge_desc_mode[] = "desc-mode";
    166 static char default_mtu[] = "default_mtu";
    167 static char low_memory_mode[] = "minimal-memory-usage";
    168 extern kmutex_t nge_log_mutex[1];
    169 
    170 static int		nge_m_start(void *);
    171 static void		nge_m_stop(void *);
    172 static int		nge_m_promisc(void *, boolean_t);
    173 static int		nge_m_multicst(void *, boolean_t, const uint8_t *);
    174 static int		nge_m_unicst(void *, const uint8_t *);
    175 static void		nge_m_ioctl(void *, queue_t *, mblk_t *);
    176 static boolean_t	nge_m_getcapab(void *, mac_capab_t, void *);
    177 static int		nge_m_setprop(void *, const char *, mac_prop_id_t,
    178 	uint_t, const void *);
    179 static int		nge_m_getprop(void *, const char *, mac_prop_id_t,
    180 	uint_t, uint_t, void *, uint_t *);
    181 static int		nge_set_priv_prop(nge_t *, const char *, uint_t,
    182 	const void *);
    183 static int		nge_get_priv_prop(nge_t *, const char *, uint_t,
    184 	uint_t, void *);
    185 
    186 #define		NGE_M_CALLBACK_FLAGS\
    187 		(MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP)
    188 
    189 static mac_callbacks_t nge_m_callbacks = {
    190 	NGE_M_CALLBACK_FLAGS,
    191 	nge_m_stat,
    192 	nge_m_start,
    193 	nge_m_stop,
    194 	nge_m_promisc,
    195 	nge_m_multicst,
    196 	nge_m_unicst,
    197 	nge_m_tx,
    198 	nge_m_ioctl,
    199 	nge_m_getcapab,
    200 	NULL,
    201 	NULL,
    202 	nge_m_setprop,
    203 	nge_m_getprop
    204 };
    205 
    206 mac_priv_prop_t nge_priv_props[] = {
    207 	{"_tx_bcopy_threshold", MAC_PROP_PERM_RW},
    208 	{"_rx_bcopy_threshold", MAC_PROP_PERM_RW},
    209 	{"_recv_max_packet", MAC_PROP_PERM_RW},
    210 	{"_poll_quiet_time", MAC_PROP_PERM_RW},
    211 	{"_poll_busy_time", MAC_PROP_PERM_RW},
    212 	{"_rx_intr_hwater", MAC_PROP_PERM_RW},
    213 	{"_rx_intr_lwater", MAC_PROP_PERM_RW},
    214 };
    215 
    216 #define	NGE_MAX_PRIV_PROPS \
    217 	(sizeof (nge_priv_props)/sizeof (mac_priv_prop_t))
    218 
    219 static int nge_add_intrs(nge_t *, int);
    220 static void nge_rem_intrs(nge_t *);
    221 static int nge_register_intrs_and_init_locks(nge_t *);
    222 
    223 /*
    224  * NGE MSI tunable:
    225  */
    226 boolean_t nge_enable_msi = B_FALSE;
    227 
    228 static enum ioc_reply
    229 nge_set_loop_mode(nge_t *ngep, uint32_t mode)
    230 {
    231 	/*
    232 	 * If the mode isn't being changed, there's nothing to do ...
    233 	 */
    234 	if (mode == ngep->param_loop_mode)
    235 		return (IOC_ACK);
    236 
    237 	/*
    238 	 * Validate the requested mode and prepare a suitable message
    239 	 * to explain the link down/up cycle that the change will
    240 	 * probably induce ...
    241 	 */
    242 	switch (mode) {
    243 	default:
    244 		return (IOC_INVAL);
    245 
    246 	case NGE_LOOP_NONE:
    247 	case NGE_LOOP_EXTERNAL_100:
    248 	case NGE_LOOP_EXTERNAL_10:
    249 	case NGE_LOOP_INTERNAL_PHY:
    250 		break;
    251 	}
    252 
    253 	/*
    254 	 * All OK; tell the caller to reprogram
    255 	 * the PHY and/or MAC for the new mode ...
    256 	 */
    257 	ngep->param_loop_mode = mode;
    258 	return (IOC_RESTART_ACK);
    259 }
    260 
    261 #undef	NGE_DBG
    262 #define	NGE_DBG		NGE_DBG_INIT
    263 
    264 /*
    265  * Utility routine to carve a slice off a chunk of allocated memory,
    266  * updating the chunk descriptor accordingly.  The size of the slice
    267  * is given by the product of the <qty> and <size> parameters.
    268  */
    269 void
    270 nge_slice_chunk(dma_area_t *slice, dma_area_t *chunk,
    271     uint32_t qty, uint32_t size)
    272 {
    273 	size_t totsize;
    274 
    275 	totsize = qty*size;
    276 	ASSERT(size > 0);
    277 	ASSERT(totsize <= chunk->alength);
    278 
    279 	*slice = *chunk;
    280 	slice->nslots = qty;
    281 	slice->size = size;
    282 	slice->alength = totsize;
    283 
    284 	chunk->mem_va = (caddr_t)chunk->mem_va + totsize;
    285 	chunk->alength -= totsize;
    286 	chunk->offset += totsize;
    287 	chunk->cookie.dmac_laddress += totsize;
    288 	chunk->cookie.dmac_size -= totsize;
    289 }
    290 
    291 /*
    292  * Allocate an area of memory and a DMA handle for accessing it
    293  */
    294 int
    295 nge_alloc_dma_mem(nge_t *ngep, size_t memsize, ddi_device_acc_attr_t *attr_p,
    296     uint_t dma_flags, dma_area_t *dma_p)
    297 {
    298 	int err;
    299 	caddr_t va;
    300 
    301 	NGE_TRACE(("nge_alloc_dma_mem($%p, %ld, $%p, 0x%x, $%p)",
    302 	    (void *)ngep, memsize, attr_p, dma_flags, dma_p));
    303 	/*
    304 	 * Allocate handle
    305 	 */
    306 	err = ddi_dma_alloc_handle(ngep->devinfo, ngep->desc_attr.dma_attr,
    307 	    DDI_DMA_DONTWAIT, NULL, &dma_p->dma_hdl);
    308 	if (err != DDI_SUCCESS)
    309 		goto fail;
    310 
    311 	/*
    312 	 * Allocate memory
    313 	 */
    314 	err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p,
    315 	    dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
    316 	    DDI_DMA_DONTWAIT, NULL, &va, &dma_p->alength, &dma_p->acc_hdl);
    317 	if (err != DDI_SUCCESS)
    318 		goto fail;
    319 
    320 	/*
    321 	 * Bind the two together
    322 	 */
    323 	dma_p->mem_va = va;
    324 	err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
    325 	    va, dma_p->alength, dma_flags, DDI_DMA_DONTWAIT, NULL,
    326 	    &dma_p->cookie, &dma_p->ncookies);
    327 
    328 	if (err != DDI_DMA_MAPPED || dma_p->ncookies != 1)
    329 		goto fail;
    330 
    331 	dma_p->nslots = ~0U;
    332 	dma_p->size = ~0U;
    333 	dma_p->offset = 0;
    334 
    335 	return (DDI_SUCCESS);
    336 
    337 fail:
    338 	nge_free_dma_mem(dma_p);
    339 	NGE_DEBUG(("nge_alloc_dma_mem: fail to alloc dma memory!"));
    340 
    341 	return (DDI_FAILURE);
    342 }
    343 
    344 /*
    345  * Free one allocated area of DMAable memory
    346  */
    347 void
    348 nge_free_dma_mem(dma_area_t *dma_p)
    349 {
    350 	if (dma_p->dma_hdl != NULL) {
    351 		if (dma_p->ncookies) {
    352 			(void) ddi_dma_unbind_handle(dma_p->dma_hdl);
    353 			dma_p->ncookies = 0;
    354 		}
    355 	}
    356 	if (dma_p->acc_hdl != NULL) {
    357 		ddi_dma_mem_free(&dma_p->acc_hdl);
    358 		dma_p->acc_hdl = NULL;
    359 	}
    360 	if (dma_p->dma_hdl != NULL) {
    361 		ddi_dma_free_handle(&dma_p->dma_hdl);
    362 		dma_p->dma_hdl = NULL;
    363 	}
    364 }
    365 
    366 #define	ALLOC_TX_BUF	0x1
    367 #define	ALLOC_TX_DESC	0x2
    368 #define	ALLOC_RX_DESC	0x4
    369 
    370 int
    371 nge_alloc_bufs(nge_t *ngep)
    372 {
    373 	int err;
    374 	int split;
    375 	int progress;
    376 	size_t txbuffsize;
    377 	size_t rxdescsize;
    378 	size_t txdescsize;
    379 
    380 	txbuffsize = ngep->tx_desc * ngep->buf_size;
    381 	rxdescsize = ngep->rx_desc;
    382 	txdescsize = ngep->tx_desc;
    383 	rxdescsize *= ngep->desc_attr.rxd_size;
    384 	txdescsize *= ngep->desc_attr.txd_size;
    385 	progress = 0;
    386 
    387 	NGE_TRACE(("nge_alloc_bufs($%p)", (void *)ngep));
    388 	/*
    389 	 * Allocate memory & handles for TX buffers
    390 	 */
    391 	ASSERT((txbuffsize % ngep->nge_split) == 0);
    392 	for (split = 0; split < ngep->nge_split; ++split) {
    393 		err = nge_alloc_dma_mem(ngep, txbuffsize/ngep->nge_split,
    394 		    &nge_data_accattr, DDI_DMA_WRITE | NGE_DMA_MODE,
    395 		    &ngep->send->buf[split]);
    396 		if (err != DDI_SUCCESS)
    397 			goto fail;
    398 	}
    399 
    400 	progress |= ALLOC_TX_BUF;
    401 
    402 	/*
    403 	 * Allocate memory & handles for receive return rings and
    404 	 * buffer (producer) descriptor rings
    405 	 */
    406 	err = nge_alloc_dma_mem(ngep, rxdescsize, &nge_desc_accattr,
    407 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &ngep->recv->desc);
    408 	if (err != DDI_SUCCESS)
    409 		goto fail;
    410 	progress |= ALLOC_RX_DESC;
    411 
    412 	/*
    413 	 * Allocate memory & handles for TX descriptor rings,
    414 	 */
    415 	err = nge_alloc_dma_mem(ngep, txdescsize, &nge_desc_accattr,
    416 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &ngep->send->desc);
    417 	if (err != DDI_SUCCESS)
    418 		goto fail;
    419 	return (DDI_SUCCESS);
    420 
    421 fail:
    422 	if (progress & ALLOC_RX_DESC)
    423 		nge_free_dma_mem(&ngep->recv->desc);
    424 	if (progress & ALLOC_TX_BUF) {
    425 		for (split = 0; split < ngep->nge_split; ++split)
    426 			nge_free_dma_mem(&ngep->send->buf[split]);
    427 	}
    428 
    429 	return (DDI_FAILURE);
    430 }
    431 
    432 /*
    433  * This routine frees the transmit and receive buffers and descriptors.
    434  * Make sure the chip is stopped before calling it!
    435  */
    436 void
    437 nge_free_bufs(nge_t *ngep)
    438 {
    439 	int split;
    440 
    441 	NGE_TRACE(("nge_free_bufs($%p)", (void *)ngep));
    442 
    443 	nge_free_dma_mem(&ngep->recv->desc);
    444 	nge_free_dma_mem(&ngep->send->desc);
    445 
    446 	for (split = 0; split < ngep->nge_split; ++split)
    447 		nge_free_dma_mem(&ngep->send->buf[split]);
    448 }
    449 
    450 /*
    451  * Clean up initialisation done above before the memory is freed
    452  */
    453 static void
    454 nge_fini_send_ring(nge_t *ngep)
    455 {
    456 	uint32_t slot;
    457 	size_t dmah_num;
    458 	send_ring_t *srp;
    459 	sw_tx_sbd_t *ssbdp;
    460 
    461 	srp = ngep->send;
    462 	ssbdp = srp->sw_sbds;
    463 
    464 	NGE_TRACE(("nge_fini_send_ring($%p)", (void *)ngep));
    465 
    466 	dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]);
    467 
    468 	for (slot = 0; slot < dmah_num; ++slot) {
    469 		if (srp->dmahndl[slot].hndl) {
    470 			(void) ddi_dma_unbind_handle(srp->dmahndl[slot].hndl);
    471 			ddi_dma_free_handle(&srp->dmahndl[slot].hndl);
    472 			srp->dmahndl[slot].hndl = NULL;
    473 			srp->dmahndl[slot].next = NULL;
    474 		}
    475 	}
    476 
    477 	srp->dmah_free.head = NULL;
    478 	srp->dmah_free.tail = NULL;
    479 
    480 	kmem_free(ssbdp, srp->desc.nslots*sizeof (*ssbdp));
    481 
    482 }
    483 
    484 /*
    485  * Initialise the specified Send Ring, using the information in the
    486  * <dma_area> descriptors that it contains to set up all the other
    487  * fields. This routine should be called only once for each ring.
    488  */
    489 static int
    490 nge_init_send_ring(nge_t *ngep)
    491 {
    492 	size_t dmah_num;
    493 	uint32_t nslots;
    494 	uint32_t err;
    495 	uint32_t slot;
    496 	uint32_t split;
    497 	send_ring_t *srp;
    498 	sw_tx_sbd_t *ssbdp;
    499 	dma_area_t desc;
    500 	dma_area_t pbuf;
    501 
    502 	srp = ngep->send;
    503 	srp->desc.nslots = ngep->tx_desc;
    504 	nslots = srp->desc.nslots;
    505 
    506 	NGE_TRACE(("nge_init_send_ring($%p)", (void *)ngep));
    507 	/*
    508 	 * Other one-off initialisation of per-ring data
    509 	 */
    510 	srp->ngep = ngep;
    511 
    512 	/*
    513 	 * Allocate the array of s/w Send Buffer Descriptors
    514 	 */
    515 	ssbdp = kmem_zalloc(nslots*sizeof (*ssbdp), KM_SLEEP);
    516 	srp->sw_sbds = ssbdp;
    517 
    518 	/*
    519 	 * Now initialise each array element once and for all
    520 	 */
    521 	desc = srp->desc;
    522 	for (split = 0; split < ngep->nge_split; ++split) {
    523 		pbuf = srp->buf[split];
    524 		for (slot = 0; slot < nslots/ngep->nge_split; ++ssbdp, ++slot) {
    525 			nge_slice_chunk(&ssbdp->desc, &desc, 1,
    526 			    ngep->desc_attr.txd_size);
    527 			nge_slice_chunk(&ssbdp->pbuf, &pbuf, 1,
    528 			    ngep->buf_size);
    529 		}
    530 		ASSERT(pbuf.alength == 0);
    531 	}
    532 	ASSERT(desc.alength == 0);
    533 
    534 	dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]);
    535 
    536 	/* preallocate dma handles for tx buffer */
    537 	for (slot = 0; slot < dmah_num; ++slot) {
    538 
    539 		err = ddi_dma_alloc_handle(ngep->devinfo,
    540 		    ngep->desc_attr.tx_dma_attr, DDI_DMA_DONTWAIT,
    541 		    NULL, &srp->dmahndl[slot].hndl);
    542 
    543 		if (err != DDI_SUCCESS) {
    544 			nge_fini_send_ring(ngep);
    545 			nge_error(ngep,
    546 			    "nge_init_send_ring: alloc dma handle fails");
    547 			return (DDI_FAILURE);
    548 		}
    549 		srp->dmahndl[slot].next = srp->dmahndl + slot + 1;
    550 	}
    551 
    552 	srp->dmah_free.head = srp->dmahndl;
    553 	srp->dmah_free.tail = srp->dmahndl + dmah_num - 1;
    554 	srp->dmah_free.tail->next = NULL;
    555 
    556 	return (DDI_SUCCESS);
    557 }
    558 
    559 /*
    560  * Intialize the tx recycle pointer and tx sending pointer of tx ring
    561  * and set the type of tx's data descriptor by default.
    562  */
    563 static void
    564 nge_reinit_send_ring(nge_t *ngep)
    565 {
    566 	size_t dmah_num;
    567 	uint32_t slot;
    568 	send_ring_t *srp;
    569 	sw_tx_sbd_t *ssbdp;
    570 
    571 	srp = ngep->send;
    572 
    573 	/*
    574 	 * Reinitialise control variables ...
    575 	 */
    576 
    577 	srp->tx_hwmark = NGE_DESC_MIN;
    578 	srp->tx_lwmark = NGE_DESC_MIN;
    579 
    580 	srp->tx_next = 0;
    581 	srp->tx_free = srp->desc.nslots;
    582 	srp->tc_next = 0;
    583 
    584 	dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]);
    585 
    586 	for (slot = 0; slot - dmah_num != 0; ++slot)
    587 		srp->dmahndl[slot].next = srp->dmahndl + slot + 1;
    588 
    589 	srp->dmah_free.head = srp->dmahndl;
    590 	srp->dmah_free.tail = srp->dmahndl + dmah_num - 1;
    591 	srp->dmah_free.tail->next = NULL;
    592 
    593 	/*
    594 	 * Zero and sync all the h/w Send Buffer Descriptors
    595 	 */
    596 	for (slot = 0; slot < srp->desc.nslots; ++slot) {
    597 		ssbdp = &srp->sw_sbds[slot];
    598 		ssbdp->flags = HOST_OWN;
    599 	}
    600 
    601 	DMA_ZERO(srp->desc);
    602 	DMA_SYNC(srp->desc, DDI_DMA_SYNC_FORDEV);
    603 }
    604 
    605 /*
    606  * Initialize the slot number of rx's ring
    607  */
    608 static void
    609 nge_init_recv_ring(nge_t *ngep)
    610 {
    611 	recv_ring_t *rrp;
    612 
    613 	rrp = ngep->recv;
    614 	rrp->desc.nslots = ngep->rx_desc;
    615 	rrp->ngep = ngep;
    616 }
    617 
    618 /*
    619  * Intialize the rx recycle pointer and rx sending pointer of rx ring
    620  */
    621 static void
    622 nge_reinit_recv_ring(nge_t *ngep)
    623 {
    624 	recv_ring_t *rrp;
    625 
    626 	rrp = ngep->recv;
    627 
    628 	/*
    629 	 * Reinitialise control variables ...
    630 	 */
    631 	rrp->prod_index = 0;
    632 	/*
    633 	 * Zero and sync all the h/w Send Buffer Descriptors
    634 	 */
    635 	DMA_ZERO(rrp->desc);
    636 	DMA_SYNC(rrp->desc, DDI_DMA_SYNC_FORDEV);
    637 }
    638 
    639 /*
    640  * Clean up initialisation done above before the memory is freed
    641  */
    642 static void
    643 nge_fini_buff_ring(nge_t *ngep)
    644 {
    645 	uint32_t i;
    646 	buff_ring_t *brp;
    647 	dma_area_t *bufp;
    648 	sw_rx_sbd_t *bsbdp;
    649 
    650 	brp = ngep->buff;
    651 	bsbdp = brp->sw_rbds;
    652 
    653 	NGE_DEBUG(("nge_fini_buff_ring($%p)", (void *)ngep));
    654 
    655 	mutex_enter(brp->recycle_lock);
    656 	brp->buf_sign++;
    657 	mutex_exit(brp->recycle_lock);
    658 	for (i = 0; i < ngep->rx_desc; i++, ++bsbdp) {
    659 		if (bsbdp->bufp) {
    660 			if (bsbdp->bufp->mp)
    661 				freemsg(bsbdp->bufp->mp);
    662 			nge_free_dma_mem(bsbdp->bufp);
    663 			kmem_free(bsbdp->bufp, sizeof (dma_area_t));
    664 			bsbdp->bufp = NULL;
    665 		}
    666 	}
    667 	while (brp->free_list != NULL) {
    668 		bufp = brp->free_list;
    669 		brp->free_list = bufp->next;
    670 		bufp->next = NULL;
    671 		if (bufp->mp)
    672 			freemsg(bufp->mp);
    673 		nge_free_dma_mem(bufp);
    674 		kmem_free(bufp, sizeof (dma_area_t));
    675 	}
    676 	while (brp->recycle_list != NULL) {
    677 		bufp = brp->recycle_list;
    678 		brp->recycle_list = bufp->next;
    679 		bufp->next = NULL;
    680 		if (bufp->mp)
    681 			freemsg(bufp->mp);
    682 		nge_free_dma_mem(bufp);
    683 		kmem_free(bufp, sizeof (dma_area_t));
    684 	}
    685 
    686 
    687 	kmem_free(brp->sw_rbds, (ngep->rx_desc * sizeof (*bsbdp)));
    688 	brp->sw_rbds = NULL;
    689 }
    690 
    691 /*
    692  * Intialize the Rx's data ring and free ring
    693  */
    694 static int
    695 nge_init_buff_ring(nge_t *ngep)
    696 {
    697 	uint32_t err;
    698 	uint32_t slot;
    699 	uint32_t nslots_buff;
    700 	uint32_t nslots_recv;
    701 	buff_ring_t *brp;
    702 	recv_ring_t *rrp;
    703 	dma_area_t desc;
    704 	dma_area_t *bufp;
    705 	sw_rx_sbd_t *bsbdp;
    706 
    707 	rrp = ngep->recv;
    708 	brp = ngep->buff;
    709 	brp->nslots = ngep->rx_buf;
    710 	brp->rx_bcopy = B_FALSE;
    711 	nslots_recv = rrp->desc.nslots;
    712 	nslots_buff = brp->nslots;
    713 	brp->ngep = ngep;
    714 
    715 	NGE_TRACE(("nge_init_buff_ring($%p)", (void *)ngep));
    716 
    717 	/*
    718 	 * Allocate the array of s/w Recv Buffer Descriptors
    719 	 */
    720 	bsbdp = kmem_zalloc(nslots_recv *sizeof (*bsbdp), KM_SLEEP);
    721 	brp->sw_rbds = bsbdp;
    722 	brp->free_list = NULL;
    723 	brp->recycle_list = NULL;
    724 	for (slot = 0; slot < nslots_buff; ++slot) {
    725 		bufp = kmem_zalloc(sizeof (dma_area_t), KM_SLEEP);
    726 		err = nge_alloc_dma_mem(ngep, (ngep->buf_size
    727 		    + NGE_HEADROOM),
    728 		    &nge_data_accattr, DDI_DMA_READ | NGE_DMA_MODE, bufp);
    729 		if (err != DDI_SUCCESS) {
    730 			kmem_free(bufp, sizeof (dma_area_t));
    731 			return (DDI_FAILURE);
    732 		}
    733 
    734 		bufp->alength -= NGE_HEADROOM;
    735 		bufp->offset += NGE_HEADROOM;
    736 		bufp->private = (caddr_t)ngep;
    737 		bufp->rx_recycle.free_func = nge_recv_recycle;
    738 		bufp->rx_recycle.free_arg = (caddr_t)bufp;
    739 		bufp->signature = brp->buf_sign;
    740 		bufp->rx_delivered = B_FALSE;
    741 		bufp->mp = desballoc(DMA_VPTR(*bufp),
    742 		    ngep->buf_size + NGE_HEADROOM,
    743 		    0, &bufp->rx_recycle);
    744 
    745 		if (bufp->mp == NULL) {
    746 			return (DDI_FAILURE);
    747 		}
    748 		bufp->next = brp->free_list;
    749 		brp->free_list = bufp;
    750 	}
    751 
    752 	/*
    753 	 * Now initialise each array element once and for all
    754 	 */
    755 	desc = rrp->desc;
    756 	for (slot = 0; slot < nslots_recv; ++slot, ++bsbdp) {
    757 		nge_slice_chunk(&bsbdp->desc, &desc, 1,
    758 		    ngep->desc_attr.rxd_size);
    759 		bufp = brp->free_list;
    760 		brp->free_list = bufp->next;
    761 		bsbdp->bufp = bufp;
    762 		bsbdp->flags = CONTROLER_OWN;
    763 		bufp->next = NULL;
    764 	}
    765 
    766 	ASSERT(desc.alength == 0);
    767 	return (DDI_SUCCESS);
    768 }
    769 
    770 /*
    771  * Fill the host address of data in rx' descriptor
    772  * and initialize free pointers of rx free ring
    773  */
    774 static int
    775 nge_reinit_buff_ring(nge_t *ngep)
    776 {
    777 	uint32_t slot;
    778 	uint32_t nslots_recv;
    779 	buff_ring_t *brp;
    780 	recv_ring_t *rrp;
    781 	sw_rx_sbd_t *bsbdp;
    782 	void *hw_bd_p;
    783 
    784 	brp = ngep->buff;
    785 	rrp = ngep->recv;
    786 	bsbdp = brp->sw_rbds;
    787 	nslots_recv = rrp->desc.nslots;
    788 	for (slot = 0; slot < nslots_recv; ++bsbdp, ++slot) {
    789 		hw_bd_p = DMA_VPTR(bsbdp->desc);
    790 	/*
    791 	 * There is a scenario: When the traffic of small tcp
    792 	 * packet is heavy, suspending the tcp traffic will
    793 	 * cause the preallocated buffers for rx not to be
    794 	 * released in time by tcp taffic and cause rx's buffer
    795 	 * pointers not to be refilled in time.
    796 	 *
    797 	 * At this point, if we reinitialize the driver, the bufp
    798 	 * pointer for rx's traffic will be NULL.
    799 	 * So the result of the reinitializion fails.
    800 	 */
    801 		if (bsbdp->bufp == NULL)
    802 			return (DDI_FAILURE);
    803 
    804 		ngep->desc_attr.rxd_fill(hw_bd_p, &bsbdp->bufp->cookie,
    805 		    bsbdp->bufp->alength);
    806 	}
    807 	return (DDI_SUCCESS);
    808 }
    809 
    810 static void
    811 nge_init_ring_param_lock(nge_t *ngep)
    812 {
    813 	buff_ring_t *brp;
    814 	send_ring_t *srp;
    815 
    816 	srp = ngep->send;
    817 	brp = ngep->buff;
    818 
    819 	/* Init the locks for send ring */
    820 	mutex_init(srp->tx_lock, NULL, MUTEX_DRIVER,
    821 	    DDI_INTR_PRI(ngep->intr_pri));
    822 	mutex_init(srp->tc_lock, NULL, MUTEX_DRIVER,
    823 	    DDI_INTR_PRI(ngep->intr_pri));
    824 	mutex_init(&srp->dmah_lock, NULL, MUTEX_DRIVER,
    825 	    DDI_INTR_PRI(ngep->intr_pri));
    826 
    827 	/* Init parameters of buffer ring */
    828 	brp->free_list = NULL;
    829 	brp->recycle_list = NULL;
    830 	brp->rx_hold = 0;
    831 	brp->buf_sign = 0;
    832 
    833 	/* Init recycle list lock */
    834 	mutex_init(brp->recycle_lock, NULL, MUTEX_DRIVER,
    835 	    DDI_INTR_PRI(ngep->intr_pri));
    836 }
    837 
    838 int
    839 nge_init_rings(nge_t *ngep)
    840 {
    841 	uint32_t err;
    842 
    843 	err = nge_init_send_ring(ngep);
    844 	if (err != DDI_SUCCESS) {
    845 		return (err);
    846 	}
    847 	nge_init_recv_ring(ngep);
    848 
    849 	err = nge_init_buff_ring(ngep);
    850 	if (err != DDI_SUCCESS) {
    851 		nge_fini_send_ring(ngep);
    852 		return (DDI_FAILURE);
    853 	}
    854 
    855 	return (err);
    856 }
    857 
    858 static int
    859 nge_reinit_ring(nge_t *ngep)
    860 {
    861 	int err;
    862 
    863 	nge_reinit_recv_ring(ngep);
    864 	nge_reinit_send_ring(ngep);
    865 	err = nge_reinit_buff_ring(ngep);
    866 	return (err);
    867 }
    868 
    869 
    870 void
    871 nge_fini_rings(nge_t *ngep)
    872 {
    873 	/*
    874 	 * For receive ring, nothing need to be finished.
    875 	 * So only finish buffer ring and send ring here.
    876 	 */
    877 	nge_fini_buff_ring(ngep);
    878 	nge_fini_send_ring(ngep);
    879 }
    880 
    881 /*
    882  * Loopback ioctl code
    883  */
    884 
    885 static lb_property_t loopmodes[] = {
    886 	{ normal,	"normal",	NGE_LOOP_NONE		},
    887 	{ external,	"100Mbps",	NGE_LOOP_EXTERNAL_100	},
    888 	{ external,	"10Mbps",	NGE_LOOP_EXTERNAL_10	},
    889 	{ internal,	"PHY",		NGE_LOOP_INTERNAL_PHY	},
    890 };
    891 
    892 enum ioc_reply
    893 nge_loop_ioctl(nge_t *ngep, mblk_t *mp, struct iocblk *iocp)
    894 {
    895 	int cmd;
    896 	uint32_t *lbmp;
    897 	lb_info_sz_t *lbsp;
    898 	lb_property_t *lbpp;
    899 
    900 	/*
    901 	 * Validate format of ioctl
    902 	 */
    903 	if (mp->b_cont == NULL)
    904 		return (IOC_INVAL);
    905 
    906 	cmd = iocp->ioc_cmd;
    907 
    908 	switch (cmd) {
    909 	default:
    910 		return (IOC_INVAL);
    911 
    912 	case LB_GET_INFO_SIZE:
    913 		if (iocp->ioc_count != sizeof (lb_info_sz_t))
    914 			return (IOC_INVAL);
    915 		lbsp = (lb_info_sz_t *)mp->b_cont->b_rptr;
    916 		*lbsp = sizeof (loopmodes);
    917 		return (IOC_REPLY);
    918 
    919 	case LB_GET_INFO:
    920 		if (iocp->ioc_count != sizeof (loopmodes))
    921 			return (IOC_INVAL);
    922 		lbpp = (lb_property_t *)mp->b_cont->b_rptr;
    923 		bcopy(loopmodes, lbpp, sizeof (loopmodes));
    924 		return (IOC_REPLY);
    925 
    926 	case LB_GET_MODE:
    927 		if (iocp->ioc_count != sizeof (uint32_t))
    928 			return (IOC_INVAL);
    929 		lbmp = (uint32_t *)mp->b_cont->b_rptr;
    930 		*lbmp = ngep->param_loop_mode;
    931 		return (IOC_REPLY);
    932 
    933 	case LB_SET_MODE:
    934 		if (iocp->ioc_count != sizeof (uint32_t))
    935 			return (IOC_INVAL);
    936 		lbmp = (uint32_t *)mp->b_cont->b_rptr;
    937 		return (nge_set_loop_mode(ngep, *lbmp));
    938 	}
    939 }
    940 
    941 #undef	NGE_DBG
    942 #define	NGE_DBG	NGE_DBG_NEMO
    943 
    944 
    945 static void
    946 nge_check_desc_prop(nge_t *ngep)
    947 {
    948 	if (ngep->desc_mode != DESC_HOT && ngep->desc_mode != DESC_OFFLOAD)
    949 		ngep->desc_mode = DESC_HOT;
    950 
    951 	if (ngep->desc_mode == DESC_OFFLOAD)	{
    952 
    953 		ngep->desc_attr = nge_sum_desc;
    954 
    955 	}	else if (ngep->desc_mode == DESC_HOT)	{
    956 
    957 		ngep->desc_attr = nge_hot_desc;
    958 	}
    959 }
    960 
    961 /*
    962  * nge_get_props -- get the parameters to tune the driver
    963  */
    964 static void
    965 nge_get_props(nge_t *ngep)
    966 {
    967 	chip_info_t *infop;
    968 	dev_info_t *devinfo;
    969 	nge_dev_spec_param_t *dev_param_p;
    970 
    971 	devinfo = ngep->devinfo;
    972 	infop = (chip_info_t *)&ngep->chipinfo;
    973 	dev_param_p = &ngep->dev_spec_param;
    974 
    975 	infop->clsize = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
    976 	    DDI_PROP_DONTPASS, clsize_propname, 32);
    977 
    978 	infop->latency = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
    979 	    DDI_PROP_DONTPASS, latency_propname, 64);
    980 	ngep->intr_moderation = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
    981 	    DDI_PROP_DONTPASS, intr_moderation, NGE_SET);
    982 	ngep->rx_datahwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
    983 	    DDI_PROP_DONTPASS, rx_data_hw, 0x20);
    984 	ngep->rx_prdlwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
    985 	    DDI_PROP_DONTPASS, rx_prd_lw, 0x4);
    986 	ngep->rx_prdhwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
    987 	    DDI_PROP_DONTPASS, rx_prd_hw, 0xc);
    988 
    989 	ngep->sw_intr_intv = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
    990 	    DDI_PROP_DONTPASS, sw_intr_intv, SWTR_ITC);
    991 	ngep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
    992 	    DDI_PROP_DONTPASS, debug_propname, NGE_DBG_CHIP);
    993 	ngep->desc_mode = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
    994 	    DDI_PROP_DONTPASS, nge_desc_mode, dev_param_p->desc_type);
    995 	ngep->lowmem_mode = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
    996 	    DDI_PROP_DONTPASS, low_memory_mode, 0);
    997 
    998 	if (dev_param_p->jumbo) {
    999 		ngep->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
   1000 		    DDI_PROP_DONTPASS, default_mtu, ETHERMTU);
   1001 	} else
   1002 		ngep->default_mtu = ETHERMTU;
   1003 	if (dev_param_p->tx_pause_frame)
   1004 			ngep->param_link_tx_pause = B_TRUE;
   1005 	else
   1006 			ngep->param_link_tx_pause = B_FALSE;
   1007 
   1008 	if (dev_param_p->rx_pause_frame)
   1009 			ngep->param_link_rx_pause = B_TRUE;
   1010 	else
   1011 			ngep->param_link_rx_pause = B_FALSE;
   1012 
   1013 	if (ngep->default_mtu > ETHERMTU &&
   1014 	    ngep->default_mtu <= NGE_MTU_2500) {
   1015 		ngep->buf_size = NGE_JB2500_BUFSZ;
   1016 		ngep->tx_desc = NGE_SEND_JB2500_SLOTS_DESC;
   1017 		ngep->rx_desc = NGE_RECV_JB2500_SLOTS_DESC;
   1018 		ngep->rx_buf = NGE_RECV_JB2500_SLOTS_DESC * 2;
   1019 		ngep->nge_split = NGE_SPLIT_256;
   1020 	} else if (ngep->default_mtu > NGE_MTU_2500 &&
   1021 	    ngep->default_mtu <= NGE_MTU_4500) {
   1022 		ngep->buf_size = NGE_JB4500_BUFSZ;
   1023 		ngep->tx_desc = NGE_SEND_JB4500_SLOTS_DESC;
   1024 		ngep->rx_desc = NGE_RECV_JB4500_SLOTS_DESC;
   1025 		ngep->rx_buf = NGE_RECV_JB4500_SLOTS_DESC * 2;
   1026 		ngep->nge_split = NGE_SPLIT_256;
   1027 	} else if (ngep->default_mtu > NGE_MTU_4500 &&
   1028 	    ngep->default_mtu <= NGE_MAX_MTU) {
   1029 		ngep->buf_size = NGE_JB9000_BUFSZ;
   1030 		ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC;
   1031 		ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC;
   1032 		ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2;
   1033 		ngep->nge_split = NGE_SPLIT_256;
   1034 	} else if (ngep->default_mtu > NGE_MAX_MTU) {
   1035 		ngep->default_mtu = NGE_MAX_MTU;
   1036 		ngep->buf_size = NGE_JB9000_BUFSZ;
   1037 		ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC;
   1038 		ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC;
   1039 		ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2;
   1040 		ngep->nge_split = NGE_SPLIT_256;
   1041 	} else if (ngep->lowmem_mode != 0) {
   1042 		ngep->default_mtu = ETHERMTU;
   1043 		ngep->buf_size = NGE_STD_BUFSZ;
   1044 		ngep->tx_desc = NGE_SEND_LOWMEM_SLOTS_DESC;
   1045 		ngep->rx_desc = NGE_RECV_LOWMEM_SLOTS_DESC;
   1046 		ngep->rx_buf = NGE_RECV_LOWMEM_SLOTS_DESC * 2;
   1047 		ngep->nge_split = NGE_SPLIT_32;
   1048 	} else {
   1049 		ngep->default_mtu = ETHERMTU;
   1050 		ngep->buf_size = NGE_STD_BUFSZ;
   1051 		ngep->tx_desc = dev_param_p->tx_desc_num;
   1052 		ngep->rx_desc = dev_param_p->rx_desc_num;
   1053 		ngep->rx_buf = dev_param_p->rx_desc_num * 2;
   1054 		ngep->nge_split = dev_param_p->nge_split;
   1055 	}
   1056 
   1057 	nge_check_desc_prop(ngep);
   1058 }
   1059 
   1060 
   1061 static int
   1062 nge_reset_dev(nge_t *ngep)
   1063 {
   1064 	int err;
   1065 	nge_mul_addr1 maddr1;
   1066 	nge_sw_statistics_t *sw_stp;
   1067 	sw_stp = &ngep->statistics.sw_statistics;
   1068 	send_ring_t *srp = ngep->send;
   1069 
   1070 	ASSERT(mutex_owned(ngep->genlock));
   1071 	mutex_enter(srp->tc_lock);
   1072 	mutex_enter(srp->tx_lock);
   1073 
   1074 	nge_tx_recycle_all(ngep);
   1075 	err = nge_reinit_ring(ngep);
   1076 	if (err == DDI_FAILURE) {
   1077 		mutex_exit(srp->tx_lock);
   1078 		mutex_exit(srp->tc_lock);
   1079 		return (err);
   1080 	}
   1081 	err = nge_chip_reset(ngep);
   1082 	/*
   1083 	 * Clear the Multicast mac address table
   1084 	 */
   1085 	nge_reg_put32(ngep, NGE_MUL_ADDR0, 0);
   1086 	maddr1.addr_val = nge_reg_get32(ngep, NGE_MUL_ADDR1);
   1087 	maddr1.addr_bits.addr = 0;
   1088 	nge_reg_put32(ngep, NGE_MUL_ADDR1, maddr1.addr_val);
   1089 
   1090 	mutex_exit(srp->tx_lock);
   1091 	mutex_exit(srp->tc_lock);
   1092 	if (err == DDI_FAILURE)
   1093 		return (err);
   1094 	ngep->watchdog = 0;
   1095 	ngep->resched_needed = B_FALSE;
   1096 	ngep->promisc = B_FALSE;
   1097 	ngep->param_loop_mode = NGE_LOOP_NONE;
   1098 	ngep->factotum_flag = 0;
   1099 	ngep->resched_needed = 0;
   1100 	ngep->nge_mac_state = NGE_MAC_RESET;
   1101 	ngep->max_sdu = ngep->default_mtu + ETHER_HEAD_LEN + ETHERFCSL;
   1102 	ngep->max_sdu += VTAG_SIZE;
   1103 	ngep->rx_def = 0x16;
   1104 
   1105 	/* Clear the software statistics */
   1106 	sw_stp->recv_count = 0;
   1107 	sw_stp->xmit_count = 0;
   1108 	sw_stp->rbytes = 0;
   1109 	sw_stp->obytes = 0;
   1110 
   1111 	return (DDI_SUCCESS);
   1112 }
   1113 
   1114 static void
   1115 nge_m_stop(void *arg)
   1116 {
   1117 	nge_t *ngep = arg;		/* private device info	*/
   1118 	int err;
   1119 
   1120 	NGE_TRACE(("nge_m_stop($%p)", arg));
   1121 
   1122 	/*
   1123 	 * Just stop processing, then record new MAC state
   1124 	 */
   1125 	mutex_enter(ngep->genlock);
   1126 	/* If suspended, the adapter is already stopped, just return. */
   1127 	if (ngep->suspended) {
   1128 		ASSERT(ngep->nge_mac_state == NGE_MAC_STOPPED);
   1129 		mutex_exit(ngep->genlock);
   1130 		return;
   1131 	}
   1132 	rw_enter(ngep->rwlock, RW_WRITER);
   1133 
   1134 	err = nge_chip_stop(ngep, B_FALSE);
   1135 	if (err == DDI_FAILURE)
   1136 		err = nge_chip_reset(ngep);
   1137 	if (err == DDI_FAILURE)
   1138 		nge_problem(ngep, "nge_m_stop: stop chip failed");
   1139 	ngep->nge_mac_state = NGE_MAC_STOPPED;
   1140 
   1141 	/* Recycle all the TX BD */
   1142 	nge_tx_recycle_all(ngep);
   1143 	nge_fini_rings(ngep);
   1144 	nge_free_bufs(ngep);
   1145 
   1146 	NGE_DEBUG(("nge_m_stop($%p) done", arg));
   1147 
   1148 	rw_exit(ngep->rwlock);
   1149 	mutex_exit(ngep->genlock);
   1150 }
   1151 
   1152 static int
   1153 nge_m_start(void *arg)
   1154 {
   1155 	int err;
   1156 	nge_t *ngep = arg;
   1157 
   1158 	NGE_TRACE(("nge_m_start($%p)", arg));
   1159 
   1160 	/*
   1161 	 * Start processing and record new MAC state
   1162 	 */
   1163 	mutex_enter(ngep->genlock);
   1164 	/*
   1165 	 * If suspended, don't start, as the resume processing
   1166 	 * will recall this function with the suspended flag off.
   1167 	 */
   1168 	if (ngep->suspended) {
   1169 		mutex_exit(ngep->genlock);
   1170 		return (EIO);
   1171 	}
   1172 	rw_enter(ngep->rwlock, RW_WRITER);
   1173 	err = nge_alloc_bufs(ngep);
   1174 	if (err != DDI_SUCCESS) {
   1175 		nge_problem(ngep, "nge_m_start: DMA buffer allocation failed");
   1176 		goto finish;
   1177 	}
   1178 	err = nge_init_rings(ngep);
   1179 	if (err != DDI_SUCCESS) {
   1180 		nge_free_bufs(ngep);
   1181 		nge_problem(ngep, "nge_init_rings() failed,err=%x", err);
   1182 		goto finish;
   1183 	}
   1184 	err = nge_restart(ngep);
   1185 
   1186 	NGE_DEBUG(("nge_m_start($%p) done", arg));
   1187 finish:
   1188 	rw_exit(ngep->rwlock);
   1189 	mutex_exit(ngep->genlock);
   1190 
   1191 	return (err == DDI_SUCCESS ? 0 : EIO);
   1192 }
   1193 
   1194 static int
   1195 nge_m_unicst(void *arg, const uint8_t *macaddr)
   1196 {
   1197 	nge_t *ngep = arg;
   1198 
   1199 	NGE_TRACE(("nge_m_unicst($%p)", arg));
   1200 	/*
   1201 	 * Remember the new current address in the driver state
   1202 	 * Sync the chip's idea of the address too ...
   1203 	 */
   1204 	mutex_enter(ngep->genlock);
   1205 
   1206 	ethaddr_copy(macaddr, ngep->cur_uni_addr.addr);
   1207 	ngep->cur_uni_addr.set = 1;
   1208 
   1209 	/*
   1210 	 * If we are suspended, we want to quit now, and not update
   1211 	 * the chip.  Doing so might put it in a bad state, but the
   1212 	 * resume will get the unicast address installed.
   1213 	 */
   1214 	if (ngep->suspended) {
   1215 		mutex_exit(ngep->genlock);
   1216 		return (DDI_SUCCESS);
   1217 	}
   1218 	nge_chip_sync(ngep);
   1219 
   1220 	NGE_DEBUG(("nge_m_unicst($%p) done", arg));
   1221 	mutex_exit(ngep->genlock);
   1222 
   1223 	return (0);
   1224 }
   1225 
   1226 static int
   1227 nge_m_promisc(void *arg, boolean_t on)
   1228 {
   1229 	nge_t *ngep = arg;
   1230 
   1231 	NGE_TRACE(("nge_m_promisc($%p)", arg));
   1232 
   1233 	/*
   1234 	 * Store specified mode and pass to chip layer to update h/w
   1235 	 */
   1236 	mutex_enter(ngep->genlock);
   1237 	/*
   1238 	 * If suspended, there is no need to do anything, even
   1239 	 * recording the promiscuious mode is not neccessary, as
   1240 	 * it won't be properly set on resume.  Just return failing.
   1241 	 */
   1242 	if (ngep->suspended) {
   1243 		mutex_exit(ngep->genlock);
   1244 		return (DDI_FAILURE);
   1245 	}
   1246 	if (ngep->promisc == on) {
   1247 		mutex_exit(ngep->genlock);
   1248 		NGE_DEBUG(("nge_m_promisc($%p) done", arg));
   1249 		return (0);
   1250 	}
   1251 	ngep->promisc = on;
   1252 	ngep->record_promisc = ngep->promisc;
   1253 	nge_chip_sync(ngep);
   1254 	NGE_DEBUG(("nge_m_promisc($%p) done", arg));
   1255 	mutex_exit(ngep->genlock);
   1256 
   1257 	return (0);
   1258 }
   1259 
   1260 static void nge_mulparam(nge_t *ngep)
   1261 {
   1262 	uint8_t number;
   1263 	ether_addr_t pand;
   1264 	ether_addr_t por;
   1265 	mul_item *plist;
   1266 
   1267 	for (number = 0; number < ETHERADDRL; number++) {
   1268 		pand[number] = 0x00;
   1269 		por[number] = 0x00;
   1270 	}
   1271 	for (plist = ngep->pcur_mulist; plist != NULL; plist = plist->next) {
   1272 		for (number = 0; number < ETHERADDRL; number++) {
   1273 			pand[number] &= plist->mul_addr[number];
   1274 			por[number] |= plist->mul_addr[number];
   1275 		}
   1276 	}
   1277 	for (number = 0; number < ETHERADDRL; number++) {
   1278 		ngep->cur_mul_addr.addr[number]
   1279 		    = pand[number] & por[number];
   1280 		ngep->cur_mul_mask.addr[number]
   1281 		    = pand [number] | (~por[number]);
   1282 	}
   1283 }
   1284 static int
   1285 nge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
   1286 {
   1287 	boolean_t update;
   1288 	boolean_t b_eq;
   1289 	nge_t *ngep = arg;
   1290 	mul_item *plist;
   1291 	mul_item *plist_prev;
   1292 	mul_item *pitem;
   1293 
   1294 	NGE_TRACE(("nge_m_multicst($%p, %s, %s)", arg,
   1295 	    (add) ? "add" : "remove", ether_sprintf((void *)mca)));
   1296 
   1297 	update = B_FALSE;
   1298 	plist = plist_prev = NULL;
   1299 	mutex_enter(ngep->genlock);
   1300 	if (add) {
   1301 		if (ngep->pcur_mulist != NULL) {
   1302 			for (plist = ngep->pcur_mulist; plist != NULL;
   1303 			    plist = plist->next) {
   1304 				b_eq = ether_eq(plist->mul_addr, mca);
   1305 				if (b_eq) {
   1306 					plist->ref_cnt++;
   1307 					break;
   1308 				}
   1309 				plist_prev = plist;
   1310 			}
   1311 		}
   1312 
   1313 		if (plist == NULL) {
   1314 			pitem = kmem_zalloc(sizeof (mul_item), KM_SLEEP);
   1315 			ether_copy(mca, pitem->mul_addr);
   1316 			pitem ->ref_cnt++;
   1317 			pitem ->next = NULL;
   1318 			if (plist_prev == NULL)
   1319 				ngep->pcur_mulist = pitem;
   1320 			else
   1321 				plist_prev->next = pitem;
   1322 			update = B_TRUE;
   1323 		}
   1324 	} else {
   1325 		if (ngep->pcur_mulist != NULL) {
   1326 			for (plist = ngep->pcur_mulist; plist != NULL;
   1327 			    plist = plist->next) {
   1328 				b_eq = ether_eq(plist->mul_addr, mca);
   1329 				if (b_eq) {
   1330 					update = B_TRUE;
   1331 					break;
   1332 				}
   1333 				plist_prev = plist;
   1334 			}
   1335 
   1336 			if (update) {
   1337 				if ((plist_prev == NULL) &&
   1338 				    (plist->next == NULL))
   1339 					ngep->pcur_mulist = NULL;
   1340 				else if ((plist_prev == NULL) &&
   1341 				    (plist->next != NULL))
   1342 					ngep->pcur_mulist = plist->next;
   1343 				else
   1344 					plist_prev->next = plist->next;
   1345 				kmem_free(plist, sizeof (mul_item));
   1346 			}
   1347 		}
   1348 	}
   1349 
   1350 	if (update && !ngep->suspended) {
   1351 		nge_mulparam(ngep);
   1352 		nge_chip_sync(ngep);
   1353 	}
   1354 	NGE_DEBUG(("nge_m_multicst($%p) done", arg));
   1355 	mutex_exit(ngep->genlock);
   1356 
   1357 	return (0);
   1358 }
   1359 
   1360 static void
   1361 nge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
   1362 {
   1363 	int err;
   1364 	int cmd;
   1365 	nge_t *ngep = arg;
   1366 	struct iocblk *iocp;
   1367 	enum ioc_reply status;
   1368 	boolean_t need_privilege;
   1369 
   1370 	/*
   1371 	 * If suspended, we might actually be able to do some of
   1372 	 * these ioctls, but it is harder to make sure they occur
   1373 	 * without actually putting the hardware in an undesireable
   1374 	 * state.  So just NAK it.
   1375 	 */
   1376 	mutex_enter(ngep->genlock);
   1377 	if (ngep->suspended) {
   1378 		miocnak(wq, mp, 0, EINVAL);
   1379 		mutex_exit(ngep->genlock);
   1380 		return;
   1381 	}
   1382 	mutex_exit(ngep->genlock);
   1383 
   1384 	/*
   1385 	 * Validate the command before bothering with the mutex ...
   1386 	 */
   1387 	iocp = (struct iocblk *)mp->b_rptr;
   1388 	iocp->ioc_error = 0;
   1389 	need_privilege = B_TRUE;
   1390 	cmd = iocp->ioc_cmd;
   1391 
   1392 	NGE_DEBUG(("nge_m_ioctl:  cmd 0x%x", cmd));
   1393 	switch (cmd) {
   1394 	default:
   1395 		NGE_LDB(NGE_DBG_BADIOC,
   1396 		    ("nge_m_ioctl: unknown cmd 0x%x", cmd));
   1397 
   1398 		miocnak(wq, mp, 0, EINVAL);
   1399 		return;
   1400 
   1401 	case NGE_MII_READ:
   1402 	case NGE_MII_WRITE:
   1403 	case NGE_SEE_READ:
   1404 	case NGE_SEE_WRITE:
   1405 	case NGE_DIAG:
   1406 	case NGE_PEEK:
   1407 	case NGE_POKE:
   1408 	case NGE_PHY_RESET:
   1409 	case NGE_SOFT_RESET:
   1410 	case NGE_HARD_RESET:
   1411 		break;
   1412 
   1413 	case LB_GET_INFO_SIZE:
   1414 	case LB_GET_INFO:
   1415 	case LB_GET_MODE:
   1416 		need_privilege = B_FALSE;
   1417 		break;
   1418 	case LB_SET_MODE:
   1419 		break;
   1420 	}
   1421 
   1422 	if (need_privilege) {
   1423 		/*
   1424 		 * Check for specific net_config privilege.
   1425 		 */
   1426 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
   1427 		if (err != 0) {
   1428 			NGE_DEBUG(("nge_m_ioctl: rejected cmd 0x%x, err %d",
   1429 			    cmd, err));
   1430 			miocnak(wq, mp, 0, err);
   1431 			return;
   1432 		}
   1433 	}
   1434 
   1435 	mutex_enter(ngep->genlock);
   1436 
   1437 	switch (cmd) {
   1438 	default:
   1439 		_NOTE(NOTREACHED)
   1440 		status = IOC_INVAL;
   1441 	break;
   1442 
   1443 	case NGE_MII_READ:
   1444 	case NGE_MII_WRITE:
   1445 	case NGE_SEE_READ:
   1446 	case NGE_SEE_WRITE:
   1447 	case NGE_DIAG:
   1448 	case NGE_PEEK:
   1449 	case NGE_POKE:
   1450 	case NGE_PHY_RESET:
   1451 	case NGE_SOFT_RESET:
   1452 	case NGE_HARD_RESET:
   1453 		status = nge_chip_ioctl(ngep, mp, iocp);
   1454 	break;
   1455 
   1456 	case LB_GET_INFO_SIZE:
   1457 	case LB_GET_INFO:
   1458 	case LB_GET_MODE:
   1459 	case LB_SET_MODE:
   1460 		status = nge_loop_ioctl(ngep, mp, iocp);
   1461 	break;
   1462 
   1463 	}
   1464 
   1465 	/*
   1466 	 * Do we need to reprogram the PHY and/or the MAC?
   1467 	 * Do it now, while we still have the mutex.
   1468 	 *
   1469 	 * Note: update the PHY first, 'cos it controls the
   1470 	 * speed/duplex parameters that the MAC code uses.
   1471 	 */
   1472 
   1473 	NGE_DEBUG(("nge_m_ioctl: cmd 0x%x status %d", cmd, status));
   1474 
   1475 	switch (status) {
   1476 	case IOC_RESTART_REPLY:
   1477 	case IOC_RESTART_ACK:
   1478 		(*ngep->physops->phys_update)(ngep);
   1479 		nge_chip_sync(ngep);
   1480 		break;
   1481 
   1482 	default:
   1483 	break;
   1484 	}
   1485 
   1486 	mutex_exit(ngep->genlock);
   1487 
   1488 	/*
   1489 	 * Finally, decide how to reply
   1490 	 */
   1491 	switch (status) {
   1492 
   1493 	default:
   1494 	case IOC_INVAL:
   1495 		miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
   1496 		    EINVAL : iocp->ioc_error);
   1497 		break;
   1498 
   1499 	case IOC_DONE:
   1500 		break;
   1501 
   1502 	case IOC_RESTART_ACK:
   1503 	case IOC_ACK:
   1504 		miocack(wq, mp, 0, 0);
   1505 		break;
   1506 
   1507 	case IOC_RESTART_REPLY:
   1508 	case IOC_REPLY:
   1509 		mp->b_datap->db_type = iocp->ioc_error == 0 ?
   1510 		    M_IOCACK : M_IOCNAK;
   1511 		qreply(wq, mp);
   1512 		break;
   1513 	}
   1514 }
   1515 
   1516 static boolean_t
   1517 nge_param_locked(mac_prop_id_t pr_num)
   1518 {
   1519 	/*
   1520 	 * All adv_* parameters are locked (read-only) while
   1521 	 * the device is in any sort of loopback mode ...
   1522 	 */
   1523 	switch (pr_num) {
   1524 		case MAC_PROP_ADV_1000FDX_CAP:
   1525 		case MAC_PROP_EN_1000FDX_CAP:
   1526 		case MAC_PROP_ADV_1000HDX_CAP:
   1527 		case MAC_PROP_EN_1000HDX_CAP:
   1528 		case MAC_PROP_ADV_100FDX_CAP:
   1529 		case MAC_PROP_EN_100FDX_CAP:
   1530 		case MAC_PROP_ADV_100HDX_CAP:
   1531 		case MAC_PROP_EN_100HDX_CAP:
   1532 		case MAC_PROP_ADV_10FDX_CAP:
   1533 		case MAC_PROP_EN_10FDX_CAP:
   1534 		case MAC_PROP_ADV_10HDX_CAP:
   1535 		case MAC_PROP_EN_10HDX_CAP:
   1536 		case MAC_PROP_AUTONEG:
   1537 		case MAC_PROP_FLOWCTRL:
   1538 			return (B_TRUE);
   1539 	}
   1540 	return (B_FALSE);
   1541 }
   1542 
   1543 /*
   1544  * callback functions for set/get of properties
   1545  */
   1546 static int
   1547 nge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
   1548     uint_t pr_valsize, const void *pr_val)
   1549 {
   1550 	nge_t *ngep = barg;
   1551 	int err = 0;
   1552 	uint32_t cur_mtu, new_mtu;
   1553 	link_flowctrl_t fl;
   1554 
   1555 	mutex_enter(ngep->genlock);
   1556 	if (ngep->param_loop_mode != NGE_LOOP_NONE &&
   1557 	    nge_param_locked(pr_num)) {
   1558 		/*
   1559 		 * All adv_* parameters are locked (read-only)
   1560 		 * while the device is in any sort of loopback mode.
   1561 		 */
   1562 		mutex_exit(ngep->genlock);
   1563 		return (EBUSY);
   1564 	}
   1565 	switch (pr_num) {
   1566 		case MAC_PROP_EN_1000FDX_CAP:
   1567 			ngep->param_en_1000fdx = *(uint8_t *)pr_val;
   1568 			ngep->param_adv_1000fdx = *(uint8_t *)pr_val;
   1569 			goto reprogram;
   1570 		case MAC_PROP_EN_100FDX_CAP:
   1571 			ngep->param_en_100fdx = *(uint8_t *)pr_val;
   1572 			ngep->param_adv_100fdx = *(uint8_t *)pr_val;
   1573 			goto reprogram;
   1574 		case MAC_PROP_EN_100HDX_CAP:
   1575 			ngep->param_en_100hdx = *(uint8_t *)pr_val;
   1576 			ngep->param_adv_100hdx = *(uint8_t *)pr_val;
   1577 			goto reprogram;
   1578 		case MAC_PROP_EN_10FDX_CAP:
   1579 			ngep->param_en_10fdx = *(uint8_t *)pr_val;
   1580 			ngep->param_adv_10fdx = *(uint8_t *)pr_val;
   1581 			goto reprogram;
   1582 		case MAC_PROP_EN_10HDX_CAP:
   1583 			ngep->param_en_10hdx = *(uint8_t *)pr_val;
   1584 			ngep->param_adv_10hdx = *(uint8_t *)pr_val;
   1585 reprogram:
   1586 		(*ngep->physops->phys_update)(ngep);
   1587 		nge_chip_sync(ngep);
   1588 		break;
   1589 
   1590 		case MAC_PROP_ADV_1000FDX_CAP:
   1591 		case MAC_PROP_ADV_1000HDX_CAP:
   1592 		case MAC_PROP_ADV_100FDX_CAP:
   1593 		case MAC_PROP_ADV_100HDX_CAP:
   1594 		case MAC_PROP_ADV_10FDX_CAP:
   1595 		case MAC_PROP_ADV_10HDX_CAP:
   1596 		case MAC_PROP_STATUS:
   1597 		case MAC_PROP_SPEED:
   1598 		case MAC_PROP_DUPLEX:
   1599 		case MAC_PROP_EN_1000HDX_CAP:
   1600 			err = ENOTSUP; /* read-only prop. Can't set this */
   1601 			break;
   1602 		case MAC_PROP_AUTONEG:
   1603 			ngep->param_adv_autoneg = *(uint8_t *)pr_val;
   1604 			(*ngep->physops->phys_update)(ngep);
   1605 			nge_chip_sync(ngep);
   1606 			break;
   1607 		case MAC_PROP_MTU:
   1608 			cur_mtu = ngep->default_mtu;
   1609 			bcopy(pr_val, &new_mtu, sizeof (new_mtu));
   1610 			if (new_mtu == cur_mtu) {
   1611 				err = 0;
   1612 				break;
   1613 			}
   1614 			if (new_mtu < ETHERMTU ||
   1615 			    new_mtu > NGE_MAX_MTU) {
   1616 				err = EINVAL;
   1617 				break;
   1618 			}
   1619 			if ((new_mtu > ETHERMTU) &&
   1620 			    (!ngep->dev_spec_param.jumbo)) {
   1621 				err = EINVAL;
   1622 				break;
   1623 			}
   1624 			if (ngep->nge_mac_state == NGE_MAC_STARTED) {
   1625 				err = EBUSY;
   1626 				break;
   1627 			}
   1628 
   1629 			ngep->default_mtu = new_mtu;
   1630 			if (ngep->default_mtu > ETHERMTU &&
   1631 			    ngep->default_mtu <= NGE_MTU_2500) {
   1632 				ngep->buf_size = NGE_JB2500_BUFSZ;
   1633 				ngep->tx_desc = NGE_SEND_JB2500_SLOTS_DESC;
   1634 				ngep->rx_desc = NGE_RECV_JB2500_SLOTS_DESC;
   1635 				ngep->rx_buf = NGE_RECV_JB2500_SLOTS_DESC * 2;
   1636 				ngep->nge_split = NGE_SPLIT_256;
   1637 			} else if (ngep->default_mtu > NGE_MTU_2500 &&
   1638 			    ngep->default_mtu <= NGE_MTU_4500) {
   1639 				ngep->buf_size = NGE_JB4500_BUFSZ;
   1640 				ngep->tx_desc = NGE_SEND_JB4500_SLOTS_DESC;
   1641 				ngep->rx_desc = NGE_RECV_JB4500_SLOTS_DESC;
   1642 				ngep->rx_buf = NGE_RECV_JB4500_SLOTS_DESC * 2;
   1643 				ngep->nge_split = NGE_SPLIT_256;
   1644 			} else if (ngep->default_mtu > NGE_MTU_4500 &&
   1645 			    ngep->default_mtu <= NGE_MAX_MTU) {
   1646 				ngep->buf_size = NGE_JB9000_BUFSZ;
   1647 				ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC;
   1648 				ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC;
   1649 				ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2;
   1650 				ngep->nge_split = NGE_SPLIT_256;
   1651 			} else if (ngep->default_mtu > NGE_MAX_MTU) {
   1652 				ngep->default_mtu = NGE_MAX_MTU;
   1653 				ngep->buf_size = NGE_JB9000_BUFSZ;
   1654 				ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC;
   1655 				ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC;
   1656 				ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2;
   1657 				ngep->nge_split = NGE_SPLIT_256;
   1658 			} else if (ngep->lowmem_mode != 0) {
   1659 				ngep->default_mtu = ETHERMTU;
   1660 				ngep->buf_size = NGE_STD_BUFSZ;
   1661 				ngep->tx_desc = NGE_SEND_LOWMEM_SLOTS_DESC;
   1662 				ngep->rx_desc = NGE_RECV_LOWMEM_SLOTS_DESC;
   1663 				ngep->rx_buf = NGE_RECV_LOWMEM_SLOTS_DESC * 2;
   1664 				ngep->nge_split = NGE_SPLIT_32;
   1665 			} else {
   1666 				ngep->default_mtu = ETHERMTU;
   1667 				ngep->buf_size = NGE_STD_BUFSZ;
   1668 				ngep->tx_desc =
   1669 				    ngep->dev_spec_param.tx_desc_num;
   1670 				ngep->rx_desc =
   1671 				    ngep->dev_spec_param.rx_desc_num;
   1672 				ngep->rx_buf =
   1673 				    ngep->dev_spec_param.rx_desc_num * 2;
   1674 				ngep->nge_split =
   1675 				    ngep->dev_spec_param.nge_split;
   1676 			}
   1677 
   1678 			err = mac_maxsdu_update(ngep->mh, ngep->default_mtu);
   1679 
   1680 			break;
   1681 		case MAC_PROP_FLOWCTRL:
   1682 			bcopy(pr_val, &fl, sizeof (fl));
   1683 			switch (fl) {
   1684 			default:
   1685 				err = ENOTSUP;
   1686 				break;
   1687 			case LINK_FLOWCTRL_NONE:
   1688 				ngep->param_adv_pause = 0;
   1689 				ngep->param_adv_asym_pause = 0;
   1690 
   1691 				ngep->param_link_rx_pause = B_FALSE;
   1692 				ngep->param_link_tx_pause = B_FALSE;
   1693 				break;
   1694 			case LINK_FLOWCTRL_RX:
   1695 				if (!((ngep->param_lp_pause == 0) &&
   1696 				    (ngep->param_lp_asym_pause == 1))) {
   1697 					err = EINVAL;
   1698 					break;
   1699 				}
   1700 				ngep->param_adv_pause = 1;
   1701 				ngep->param_adv_asym_pause = 1;
   1702 
   1703 				ngep->param_link_rx_pause = B_TRUE;
   1704 				ngep->param_link_tx_pause = B_FALSE;
   1705 				break;
   1706 			case LINK_FLOWCTRL_TX:
   1707 				if (!((ngep->param_lp_pause == 1) &&
   1708 				    (ngep->param_lp_asym_pause == 1))) {
   1709 					err = EINVAL;
   1710 					break;
   1711 				}
   1712 				ngep->param_adv_pause = 0;
   1713 				ngep->param_adv_asym_pause = 1;
   1714 
   1715 				ngep->param_link_rx_pause = B_FALSE;
   1716 				ngep->param_link_tx_pause = B_TRUE;
   1717 				break;
   1718 			case LINK_FLOWCTRL_BI:
   1719 				if (ngep->param_lp_pause != 1) {
   1720 					err = EINVAL;
   1721 					break;
   1722 				}
   1723 				ngep->param_adv_pause = 1;
   1724 
   1725 				ngep->param_link_rx_pause = B_TRUE;
   1726 				ngep->param_link_tx_pause = B_TRUE;
   1727 				break;
   1728 			}
   1729 
   1730 			if (err == 0) {
   1731 				(*ngep->physops->phys_update)(ngep);
   1732 				nge_chip_sync(ngep);
   1733 			}
   1734 
   1735 			break;
   1736 		case MAC_PROP_PRIVATE:
   1737 			err = nge_set_priv_prop(ngep, pr_name, pr_valsize,
   1738 			    pr_val);
   1739 			if (err == 0) {
   1740 				(*ngep->physops->phys_update)(ngep);
   1741 				nge_chip_sync(ngep);
   1742 			}
   1743 			break;
   1744 		default:
   1745 			err = ENOTSUP;
   1746 	}
   1747 	mutex_exit(ngep->genlock);
   1748 	return (err);
   1749 }
   1750 
   1751 static int
   1752 nge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
   1753     uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm)
   1754 {
   1755 	nge_t *ngep = barg;
   1756 	int err = 0;
   1757 	link_flowctrl_t fl;
   1758 	uint64_t speed;
   1759 	boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT);
   1760 
   1761 	if (pr_valsize == 0)
   1762 		return (EINVAL);
   1763 
   1764 	*perm = MAC_PROP_PERM_RW;
   1765 
   1766 	bzero(pr_val, pr_valsize);
   1767 
   1768 	switch (pr_num) {
   1769 		case MAC_PROP_DUPLEX:
   1770 			*perm = MAC_PROP_PERM_READ;
   1771 			if (pr_valsize >= sizeof (link_duplex_t)) {
   1772 				bcopy(&ngep->param_link_duplex, pr_val,
   1773 				    sizeof (link_duplex_t));
   1774 			} else
   1775 				err = EINVAL;
   1776 			break;
   1777 		case MAC_PROP_SPEED:
   1778 			*perm = MAC_PROP_PERM_READ;
   1779 			if (pr_valsize >= sizeof (uint64_t)) {
   1780 				speed = ngep->param_link_speed * 1000000ull;
   1781 				bcopy(&speed, pr_val, sizeof (speed));
   1782 			} else
   1783 				err = EINVAL;
   1784 			break;
   1785 		case MAC_PROP_AUTONEG:
   1786 			if (is_default) {
   1787 				*(uint8_t *)pr_val = 1;
   1788 			} else {
   1789 				*(uint8_t *)pr_val = ngep->param_adv_autoneg;
   1790 			}
   1791 			break;
   1792 		case MAC_PROP_FLOWCTRL:
   1793 			if (pr_valsize >= sizeof (link_flowctrl_t)) {
   1794 				if (pr_flags & MAC_PROP_DEFAULT) {
   1795 					fl = LINK_FLOWCTRL_BI;
   1796 					bcopy(&fl, pr_val, sizeof (fl));
   1797 					break;
   1798 				}
   1799 				if (ngep->param_link_rx_pause &&
   1800 				    !ngep->param_link_tx_pause)
   1801 					fl = LINK_FLOWCTRL_RX;
   1802 
   1803 				if (!ngep->param_link_rx_pause &&
   1804 				    !ngep->param_link_tx_pause)
   1805 					fl = LINK_FLOWCTRL_NONE;
   1806 
   1807 				if (!ngep->param_link_rx_pause &&
   1808 				    ngep->param_link_tx_pause)
   1809 					fl = LINK_FLOWCTRL_TX;
   1810 
   1811 				if (ngep->param_link_rx_pause &&
   1812 				    ngep->param_link_tx_pause)
   1813 					fl = LINK_FLOWCTRL_BI;
   1814 				bcopy(&fl, pr_val, sizeof (fl));
   1815 			} else
   1816 				err = EINVAL;
   1817 			break;
   1818 		case MAC_PROP_ADV_1000FDX_CAP:
   1819 			*perm = MAC_PROP_PERM_READ;
   1820 			if (is_default) {
   1821 				*(uint8_t *)pr_val = 1;
   1822 			} else {
   1823 				*(uint8_t *)pr_val = ngep->param_adv_1000fdx;
   1824 			}
   1825 			break;
   1826 		case MAC_PROP_EN_1000FDX_CAP:
   1827 			if (is_default) {
   1828 				*(uint8_t *)pr_val = 1;
   1829 			} else {
   1830 				*(uint8_t *)pr_val = ngep->param_en_1000fdx;
   1831 			}
   1832 			break;
   1833 		case MAC_PROP_ADV_1000HDX_CAP:
   1834 			*perm = MAC_PROP_PERM_READ;
   1835 			if (is_default) {
   1836 				*(uint8_t *)pr_val = 0;
   1837 			} else {
   1838 				*(uint8_t *)pr_val = ngep->param_adv_1000hdx;
   1839 			}
   1840 			break;
   1841 		case MAC_PROP_EN_1000HDX_CAP:
   1842 			*perm = MAC_PROP_PERM_READ;
   1843 			if (is_default) {
   1844 				*(uint8_t *)pr_val = 0;
   1845 			} else {
   1846 				*(uint8_t *)pr_val = ngep->param_en_1000hdx;
   1847 			}
   1848 			break;
   1849 		case MAC_PROP_ADV_100FDX_CAP:
   1850 			*perm = MAC_PROP_PERM_READ;
   1851 			if (is_default) {
   1852 				*(uint8_t *)pr_val = 1;
   1853 			} else {
   1854 				*(uint8_t *)pr_val = ngep->param_adv_100fdx;
   1855 			}
   1856 			break;
   1857 		case MAC_PROP_EN_100FDX_CAP:
   1858 			if (is_default) {
   1859 				*(uint8_t *)pr_val = 1;
   1860 			} else {
   1861 				*(uint8_t *)pr_val = ngep->param_en_100fdx;
   1862 			}
   1863 			break;
   1864 		case MAC_PROP_ADV_100HDX_CAP:
   1865 			*perm = MAC_PROP_PERM_READ;
   1866 			if (is_default) {
   1867 				*(uint8_t *)pr_val = 1;
   1868 			} else {
   1869 				*(uint8_t *)pr_val = ngep->param_adv_100hdx;
   1870 			}
   1871 			break;
   1872 		case MAC_PROP_EN_100HDX_CAP:
   1873 			if (is_default) {
   1874 				*(uint8_t *)pr_val = 1;
   1875 			} else {
   1876 				*(uint8_t *)pr_val = ngep->param_en_100hdx;
   1877 			}
   1878 			break;
   1879 		case MAC_PROP_ADV_10FDX_CAP:
   1880 			*perm = MAC_PROP_PERM_READ;
   1881 			if (is_default) {
   1882 				*(uint8_t *)pr_val = 1;
   1883 			} else {
   1884 				*(uint8_t *)pr_val = ngep->param_adv_10fdx;
   1885 			}
   1886 			break;
   1887 		case MAC_PROP_EN_10FDX_CAP:
   1888 			if (is_default) {
   1889 				*(uint8_t *)pr_val = 1;
   1890 			} else {
   1891 				*(uint8_t *)pr_val = ngep->param_en_10fdx;
   1892 			}
   1893 			break;
   1894 		case MAC_PROP_ADV_10HDX_CAP:
   1895 			*perm = MAC_PROP_PERM_READ;
   1896 			if (is_default) {
   1897 				*(uint8_t *)pr_val = 1;
   1898 			} else {
   1899 				*(uint8_t *)pr_val = ngep->param_adv_10hdx;
   1900 			}
   1901 			break;
   1902 		case MAC_PROP_EN_10HDX_CAP:
   1903 			if (is_default) {
   1904 				*(uint8_t *)pr_val = 1;
   1905 			} else {
   1906 				*(uint8_t *)pr_val = ngep->param_en_10hdx;
   1907 			}
   1908 			break;
   1909 		case MAC_PROP_ADV_100T4_CAP:
   1910 		case MAC_PROP_EN_100T4_CAP:
   1911 			*perm = MAC_PROP_PERM_READ;
   1912 			*(uint8_t *)pr_val = 0;
   1913 			break;
   1914 		case MAC_PROP_PRIVATE:
   1915 			err = nge_get_priv_prop(ngep, pr_name, pr_flags,
   1916 			    pr_valsize, pr_val);
   1917 			break;
   1918 		case MAC_PROP_MTU: {
   1919 			mac_propval_range_t range;
   1920 
   1921 			if (!(pr_flags & MAC_PROP_POSSIBLE))
   1922 				return (ENOTSUP);
   1923 			if (pr_valsize < sizeof (mac_propval_range_t))
   1924 				return (EINVAL);
   1925 			range.mpr_count = 1;
   1926 			range.mpr_type = MAC_PROPVAL_UINT32;
   1927 			range.range_uint32[0].mpur_min =
   1928 			    range.range_uint32[0].mpur_max = ETHERMTU;
   1929 			if (ngep->dev_spec_param.jumbo)
   1930 				range.range_uint32[0].mpur_max = NGE_MAX_MTU;
   1931 			bcopy(&range, pr_val, sizeof (range));
   1932 			break;
   1933 		}
   1934 		default:
   1935 			err = ENOTSUP;
   1936 	}
   1937 	return (err);
   1938 }
   1939 
   1940 /* ARGSUSED */
   1941 static int
   1942 nge_set_priv_prop(nge_t *ngep, const char *pr_name, uint_t pr_valsize,
   1943     const void *pr_val)
   1944 {
   1945 	int err = 0;
   1946 	long result;
   1947 
   1948 	if (strcmp(pr_name, "_tx_bcopy_threshold") == 0) {
   1949 		if (pr_val == NULL) {
   1950 			err = EINVAL;
   1951 			return (err);
   1952 		}
   1953 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
   1954 		if (result < 0 || result > NGE_MAX_SDU) {
   1955 			err = EINVAL;
   1956 		} else {
   1957 			ngep->param_txbcopy_threshold = (uint32_t)result;
   1958 			goto reprogram;
   1959 		}
   1960 		return (err);
   1961 	}
   1962 	if (strcmp(pr_name, "_rx_bcopy_threshold") == 0) {
   1963 		if (pr_val == NULL) {
   1964 			err = EINVAL;
   1965 			return (err);
   1966 		}
   1967 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
   1968 		if (result < 0 || result > NGE_MAX_SDU) {
   1969 			err = EINVAL;
   1970 		} else {
   1971 			ngep->param_rxbcopy_threshold = (uint32_t)result;
   1972 			goto reprogram;
   1973 		}
   1974 		return (err);
   1975 	}
   1976 	if (strcmp(pr_name, "_recv_max_packet") == 0) {
   1977 		if (pr_val == NULL) {
   1978 			err = EINVAL;
   1979 			return (err);
   1980 		}
   1981 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
   1982 		if (result < 0 || result > NGE_RECV_SLOTS_DESC_1024) {
   1983 			err = EINVAL;
   1984 		} else {
   1985 			ngep->param_recv_max_packet = (uint32_t)result;
   1986 			goto reprogram;
   1987 		}
   1988 		return (err);
   1989 	}
   1990 	if (strcmp(pr_name, "_poll_quiet_time") == 0) {
   1991 		if (pr_val == NULL) {
   1992 			err = EINVAL;
   1993 			return (err);
   1994 		}
   1995 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
   1996 		if (result < 0 || result > 10000) {
   1997 			err = EINVAL;
   1998 		} else {
   1999 			ngep->param_poll_quiet_time = (uint32_t)result;
   2000 			goto reprogram;
   2001 		}
   2002 		return (err);
   2003 	}
   2004 	if (strcmp(pr_name, "_poll_busy_time") == 0) {
   2005 		if (pr_val == NULL) {
   2006 			err = EINVAL;
   2007 			return (err);
   2008 		}
   2009 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
   2010 		if (result < 0 || result > 10000) {
   2011 			err = EINVAL;
   2012 		} else {
   2013 			ngep->param_poll_busy_time = (uint32_t)result;
   2014 			goto reprogram;
   2015 		}
   2016 		return (err);
   2017 	}
   2018 	if (strcmp(pr_name, "_rx_intr_hwater") == 0) {
   2019 		if (pr_val == NULL) {
   2020 			err = EINVAL;
   2021 			return (err);
   2022 		}
   2023 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
   2024 		if (result < 0 || result > NGE_RECV_SLOTS_DESC_1024) {
   2025 			err = EINVAL;
   2026 		} else {
   2027 			ngep->param_rx_intr_hwater = (uint32_t)result;
   2028 			goto reprogram;
   2029 		}
   2030 		return (err);
   2031 	}
   2032 	if (strcmp(pr_name, "_rx_intr_lwater") == 0) {
   2033 		if (pr_val == NULL) {
   2034 			err = EINVAL;
   2035 			return (err);
   2036 		}
   2037 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
   2038 		if (result < 0 || result > NGE_RECV_SLOTS_DESC_1024) {
   2039 			err = EINVAL;
   2040 		} else {
   2041 			ngep->param_rx_intr_lwater = (uint32_t)result;
   2042 			goto reprogram;
   2043 		}
   2044 		return (err);
   2045 	}
   2046 	err = ENOTSUP;
   2047 	return (err);
   2048 
   2049 reprogram:
   2050 	if (err == 0) {
   2051 		(*ngep->physops->phys_update)(ngep);
   2052 		nge_chip_sync(ngep);
   2053 	}
   2054 
   2055 	return (err);
   2056 }
   2057 
   2058 static int
   2059 nge_get_priv_prop(nge_t *ngep, const char *pr_name, uint_t pr_flags,
   2060     uint_t pr_valsize, void *pr_val)
   2061 {
   2062 	int err = ENOTSUP;
   2063 	boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT);
   2064 	int value;
   2065 
   2066 	if (strcmp(pr_name, "_tx_bcopy_threshold") == 0) {
   2067 		value = (is_default ? NGE_TX_COPY_SIZE :
   2068 		    ngep->param_txbcopy_threshold);
   2069 		err = 0;
   2070 		goto done;
   2071 	}
   2072 	if (strcmp(pr_name, "_rx_bcopy_threshold") == 0) {
   2073 		value = (is_default ? NGE_RX_COPY_SIZE :
   2074 		    ngep->param_rxbcopy_threshold);
   2075 		err = 0;
   2076 		goto done;
   2077 	}
   2078 	if (strcmp(pr_name, "_recv_max_packet") == 0) {
   2079 		value = (is_default ? 128 : ngep->param_recv_max_packet);
   2080 		err = 0;
   2081 		goto done;
   2082 	}
   2083 	if (strcmp(pr_name, "_poll_quiet_time") == 0) {
   2084 		value = (is_default ? NGE_POLL_QUIET_TIME :
   2085 		    ngep->param_poll_quiet_time);
   2086 		err = 0;
   2087 		goto done;
   2088 	}
   2089 	if (strcmp(pr_name, "_poll_busy_time") == 0) {
   2090 		value = (is_default ? NGE_POLL_BUSY_TIME :
   2091 		    ngep->param_poll_busy_time);
   2092 		err = 0;
   2093 		goto done;
   2094 	}
   2095 	if (strcmp(pr_name, "_rx_intr_hwater") == 0) {
   2096 		value = (is_default ? 1 : ngep->param_rx_intr_hwater);
   2097 		err = 0;
   2098 		goto done;
   2099 	}
   2100 	if (strcmp(pr_name, "_rx_intr_lwater") == 0) {
   2101 		value = (is_default ? 8 : ngep->param_rx_intr_lwater);
   2102 		err = 0;
   2103 		goto done;
   2104 	}
   2105 
   2106 done:
   2107 	if (err == 0) {
   2108 		(void) snprintf(pr_val, pr_valsize, "%d", value);
   2109 	}
   2110 	return (err);
   2111 }
   2112 
   2113 /* ARGSUSED */
   2114 static boolean_t
   2115 nge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
   2116 {
   2117 	nge_t	*ngep = arg;
   2118 	nge_dev_spec_param_t *dev_param_p;
   2119 
   2120 	dev_param_p = &ngep->dev_spec_param;
   2121 
   2122 	switch (cap) {
   2123 	case MAC_CAPAB_HCKSUM: {
   2124 		uint32_t *hcksum_txflags = cap_data;
   2125 
   2126 		if (dev_param_p->tx_hw_checksum) {
   2127 			*hcksum_txflags = dev_param_p->tx_hw_checksum;
   2128 		} else
   2129 			return (B_FALSE);
   2130 		break;
   2131 	}
   2132 	default:
   2133 		return (B_FALSE);
   2134 	}
   2135 	return (B_TRUE);
   2136 }
   2137 
   2138 #undef	NGE_DBG
   2139 #define	NGE_DBG	NGE_DBG_INIT	/* debug flag for this code	*/
   2140 int
   2141 nge_restart(nge_t *ngep)
   2142 {
   2143 	int err = 0;
   2144 	err = nge_reset_dev(ngep);
   2145 	/* write back the promisc setting */
   2146 	ngep->promisc = ngep->record_promisc;
   2147 	nge_chip_sync(ngep);
   2148 	if (!err)
   2149 		err = nge_chip_start(ngep);
   2150 
   2151 	if (err) {
   2152 		ngep->nge_mac_state = NGE_MAC_STOPPED;
   2153 		return (DDI_FAILURE);
   2154 	} else {
   2155 		ngep->nge_mac_state = NGE_MAC_STARTED;
   2156 		return (DDI_SUCCESS);
   2157 	}
   2158 }
   2159 
   2160 void
   2161 nge_wake_factotum(nge_t *ngep)
   2162 {
   2163 	mutex_enter(ngep->softlock);
   2164 	if (ngep->factotum_flag == 0) {
   2165 		ngep->factotum_flag = 1;
   2166 		(void) ddi_intr_trigger_softint(ngep->factotum_hdl, NULL);
   2167 	}
   2168 	mutex_exit(ngep->softlock);
   2169 }
   2170 
   2171 void
   2172 nge_interrupt_optimize(nge_t *ngep)
   2173 {
   2174 	uint32_t tx_pkts;
   2175 	tx_pkts = ngep->statistics.sw_statistics.xmit_count - ngep->tpkts_last;
   2176 	ngep->tpkts_last = ngep->statistics.sw_statistics.xmit_count;
   2177 	if ((tx_pkts > NGE_POLL_TUNE) &&
   2178 	    (tx_pkts <= NGE_POLL_MAX))
   2179 		ngep->tfint_threshold = (tx_pkts / NGE_POLL_ENTER);
   2180 	else
   2181 		ngep->tfint_threshold = NGE_TFINT_DEFAULT;
   2182 }
   2183 
   2184 /*
   2185  * High-level cyclic handler
   2186  *
   2187  * This routine schedules a (low-level) softint callback to the
   2188  * factotum.
   2189  */
   2190 
   2191 static void
   2192 nge_chip_cyclic(void *arg)
   2193 {
   2194 	nge_t *ngep;
   2195 
   2196 	ngep = (nge_t *)arg;
   2197 
   2198 	switch (ngep->nge_chip_state) {
   2199 	default:
   2200 		return;
   2201 
   2202 	case NGE_CHIP_RUNNING:
   2203 		nge_interrupt_optimize(ngep);
   2204 		break;
   2205 
   2206 	case NGE_CHIP_FAULT:
   2207 	case NGE_CHIP_ERROR:
   2208 		break;
   2209 	}
   2210 
   2211 	nge_wake_factotum(ngep);
   2212 }
   2213 
   2214 /*
   2215  * Get/Release semaphore of SMU
   2216  * For SMU enabled chipset
   2217  * When nge driver is attached, driver should acquire
   2218  * semaphore before PHY init and accessing MAC registers.
   2219  * When nge driver is unattached, driver should release
   2220  * semaphore.
   2221  */
   2222 
   2223 static int
   2224 nge_smu_sema(nge_t *ngep, boolean_t acquire)
   2225 {
   2226 	nge_tx_en tx_en;
   2227 	uint32_t tries;
   2228 
   2229 	if (acquire) {
   2230 		for (tries = 0; tries < 5; tries++) {
   2231 			tx_en.val = nge_reg_get32(ngep, NGE_TX_EN);
   2232 			if (tx_en.bits.smu2mac == NGE_SMU_FREE)
   2233 				break;
   2234 			delay(drv_usectohz(1000000));
   2235 		}
   2236 		if (tx_en.bits.smu2mac != NGE_SMU_FREE)
   2237 			return (DDI_FAILURE);
   2238 		for (tries = 0; tries < 5; tries++) {
   2239 			tx_en.val = nge_reg_get32(ngep, NGE_TX_EN);
   2240 			tx_en.bits.mac2smu = NGE_SMU_GET;
   2241 			nge_reg_put32(ngep, NGE_TX_EN, tx_en.val);
   2242 			tx_en.val = nge_reg_get32(ngep, NGE_TX_EN);
   2243 
   2244 			if (tx_en.bits.mac2smu == NGE_SMU_GET &&
   2245 			    tx_en.bits.smu2mac == NGE_SMU_FREE)
   2246 				return (DDI_SUCCESS);
   2247 			drv_usecwait(10);
   2248 		}
   2249 		return (DDI_FAILURE);
   2250 	} else
   2251 		nge_reg_put32(ngep, NGE_TX_EN, 0x0);
   2252 
   2253 	return (DDI_SUCCESS);
   2254 
   2255 }
   2256 static void
   2257 nge_unattach(nge_t *ngep)
   2258 {
   2259 	send_ring_t *srp;
   2260 	buff_ring_t *brp;
   2261 
   2262 	srp = ngep->send;
   2263 	brp = ngep->buff;
   2264 	NGE_TRACE(("nge_unattach($%p)", (void *)ngep));
   2265 
   2266 	/*
   2267 	 * Flag that no more activity may be initiated
   2268 	 */
   2269 	ngep->progress &= ~PROGRESS_READY;
   2270 	ngep->nge_mac_state = NGE_MAC_UNATTACH;
   2271 
   2272 	/*
   2273 	 * Quiesce the PHY and MAC (leave it reset but still powered).
   2274 	 * Clean up and free all NGE data structures
   2275 	 */
   2276 	if (ngep->periodic_id != NULL) {
   2277 		ddi_periodic_delete(ngep->periodic_id);
   2278 		ngep->periodic_id = NULL;
   2279 	}
   2280 
   2281 	if (ngep->progress & PROGRESS_KSTATS)
   2282 		nge_fini_kstats(ngep);
   2283 
   2284 	if (ngep->progress & PROGRESS_HWINT) {
   2285 		mutex_enter(ngep->genlock);
   2286 		nge_restore_mac_addr(ngep);
   2287 		(void) nge_chip_stop(ngep, B_FALSE);
   2288 		if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 ||
   2289 		    ngep->chipinfo.device == DEVICE_ID_MCP55_372) {
   2290 			(void) nge_smu_sema(ngep, B_FALSE);
   2291 		}
   2292 		mutex_exit(ngep->genlock);
   2293 	}
   2294 
   2295 	if (ngep->progress & PROGRESS_SWINT)
   2296 		nge_rem_intrs(ngep);
   2297 
   2298 	if (ngep->progress & PROGRESS_FACTOTUM)
   2299 		(void) ddi_intr_remove_softint(ngep->factotum_hdl);
   2300 
   2301 	if (ngep->progress & PROGRESS_RESCHED)
   2302 		(void) ddi_intr_remove_softint(ngep->resched_hdl);
   2303 
   2304 	if (ngep->progress & PROGRESS_INTR) {
   2305 		mutex_destroy(srp->tx_lock);
   2306 		mutex_destroy(srp->tc_lock);
   2307 		mutex_destroy(&srp->dmah_lock);
   2308 		mutex_destroy(brp->recycle_lock);
   2309 
   2310 		mutex_destroy(ngep->genlock);
   2311 		mutex_destroy(ngep->softlock);
   2312 		rw_destroy(ngep->rwlock);
   2313 	}
   2314 
   2315 	if (ngep->progress & PROGRESS_REGS)
   2316 		ddi_regs_map_free(&ngep->io_handle);
   2317 
   2318 	if (ngep->progress & PROGRESS_CFG)
   2319 		pci_config_teardown(&ngep->cfg_handle);
   2320 
   2321 	ddi_remove_minor_node(ngep->devinfo, NULL);
   2322 
   2323 	kmem_free(ngep, sizeof (*ngep));
   2324 }
   2325 
   2326 static int
   2327 nge_resume(dev_info_t *devinfo)
   2328 {
   2329 	nge_t		*ngep;
   2330 	chip_info_t	*infop;
   2331 	int 		err;
   2332 
   2333 	ASSERT(devinfo != NULL);
   2334 
   2335 	ngep = ddi_get_driver_private(devinfo);
   2336 	err = 0;
   2337 
   2338 	/*
   2339 	 * If there are state inconsistancies, this is bad.  Returning
   2340 	 * DDI_FAILURE here will eventually cause the machine to panic,
   2341 	 * so it is best done here so that there is a possibility of
   2342 	 * debugging the problem.
   2343 	 */
   2344 	if (ngep == NULL)
   2345 		cmn_err(CE_PANIC,
   2346 		    "nge: ngep returned from ddi_get_driver_private was NULL");
   2347 	infop = (chip_info_t *)&ngep->chipinfo;
   2348 
   2349 	if (ngep->devinfo != devinfo)
   2350 		cmn_err(CE_PANIC,
   2351 		    "nge: passed devinfo not the same as saved devinfo");
   2352 
   2353 	mutex_enter(ngep->genlock);
   2354 	rw_enter(ngep->rwlock, RW_WRITER);
   2355 
   2356 	/*
   2357 	 * Fetch the config space.  Even though we have most of it cached,
   2358 	 * some values *might* change across a suspend/resume.
   2359 	 */
   2360 	nge_chip_cfg_init(ngep, infop, B_FALSE);
   2361 
   2362 	/*
   2363 	 * Only in one case, this conditional branch can be executed: the port
   2364 	 * hasn't been plumbed.
   2365 	 */
   2366 	if (ngep->suspended == B_FALSE) {
   2367 		rw_exit(ngep->rwlock);
   2368 		mutex_exit(ngep->genlock);
   2369 		return (DDI_SUCCESS);
   2370 	}
   2371 
   2372 	nge_tx_recycle_all(ngep);
   2373 	err = nge_reinit_ring(ngep);
   2374 	if (!err) {
   2375 		err = nge_chip_reset(ngep);
   2376 		if (!err)
   2377 			err = nge_chip_start(ngep);
   2378 	}
   2379 
   2380 	if (err) {
   2381 		/*
   2382 		 * We note the failure, but return success, as the
   2383 		 * system is still usable without this controller.
   2384 		 */
   2385 		cmn_err(CE_WARN, "nge: resume: failed to restart controller");
   2386 	} else {
   2387 		ngep->nge_mac_state = NGE_MAC_STARTED;
   2388 	}
   2389 	ngep->suspended = B_FALSE;
   2390 
   2391 	rw_exit(ngep->rwlock);
   2392 	mutex_exit(ngep->genlock);
   2393 
   2394 	return (DDI_SUCCESS);
   2395 }
   2396 
   2397 /*
   2398  * attach(9E) -- Attach a device to the system
   2399  *
   2400  * Called once for each board successfully probed.
   2401  */
   2402 static int
   2403 nge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
   2404 {
   2405 	int		err;
   2406 	int		i;
   2407 	int		instance;
   2408 	caddr_t		regs;
   2409 	nge_t		*ngep;
   2410 	chip_info_t	*infop;
   2411 	mac_register_t	*macp;
   2412 
   2413 	switch (cmd) {
   2414 	default:
   2415 		return (DDI_FAILURE);
   2416 
   2417 	case DDI_RESUME:
   2418 		return (nge_resume(devinfo));
   2419 
   2420 	case DDI_ATTACH:
   2421 		break;
   2422 	}
   2423 
   2424 	ngep = kmem_zalloc(sizeof (*ngep), KM_SLEEP);
   2425 	instance = ddi_get_instance(devinfo);
   2426 	ddi_set_driver_private(devinfo, ngep);
   2427 	ngep->devinfo = devinfo;
   2428 
   2429 	(void) snprintf(ngep->ifname, sizeof (ngep->ifname), "%s%d",
   2430 	    NGE_DRIVER_NAME, instance);
   2431 	err = pci_config_setup(devinfo, &ngep->cfg_handle);
   2432 	if (err != DDI_SUCCESS) {
   2433 		nge_problem(ngep, "nge_attach: pci_config_setup() failed");
   2434 		goto attach_fail;
   2435 	}
   2436 	/*
   2437 	 * param_txbcopy_threshold and param_rxbcopy_threshold are tx/rx bcopy
   2438 	 * thresholds. Bounds: min 0, max NGE_MAX_SDU
   2439 	 */
   2440 	ngep->param_txbcopy_threshold = NGE_TX_COPY_SIZE;
   2441 	ngep->param_rxbcopy_threshold = NGE_RX_COPY_SIZE;
   2442 
   2443 	/*
   2444 	 * param_recv_max_packet is max packet received per interupt.
   2445 	 * Bounds: min 0, max NGE_RECV_SLOTS_DESC_1024
   2446 	 */
   2447 	ngep->param_recv_max_packet = 128;
   2448 
   2449 	/*
   2450 	 * param_poll_quiet_time and param_poll_busy_time are quiet/busy time
   2451 	 * switch from per packet interrupt to polling interrupt.
   2452 	 * Bounds: min 0, max 10000
   2453 	 */
   2454 	ngep->param_poll_quiet_time = NGE_POLL_QUIET_TIME;
   2455 	ngep->param_poll_busy_time = NGE_POLL_BUSY_TIME;
   2456 	ngep->tfint_threshold = NGE_TFINT_DEFAULT;
   2457 	ngep->poll = B_FALSE;
   2458 	ngep->ch_intr_mode = B_FALSE;
   2459 
   2460 	/*
   2461 	 * param_rx_intr_hwater/param_rx_intr_lwater: ackets received
   2462 	 * to trigger the poll_quiet_time/poll_busy_time counter.
   2463 	 * Bounds: min 0, max  NGE_RECV_SLOTS_DESC_1024.
   2464 	 */
   2465 	ngep->param_rx_intr_hwater = 1;
   2466 	ngep->param_rx_intr_lwater = 8;
   2467 
   2468 
   2469 	infop = (chip_info_t *)&ngep->chipinfo;
   2470 	nge_chip_cfg_init(ngep, infop, B_FALSE);
   2471 	nge_init_dev_spec_param(ngep);
   2472 	nge_get_props(ngep);
   2473 	ngep->progress |= PROGRESS_CFG;
   2474 
   2475 	err = ddi_regs_map_setup(devinfo, NGE_PCI_OPREGS_RNUMBER,
   2476 	    &regs, 0, 0, &nge_reg_accattr, &ngep->io_handle);
   2477 	if (err != DDI_SUCCESS) {
   2478 		nge_problem(ngep, "nge_attach: ddi_regs_map_setup() failed");
   2479 		goto attach_fail;
   2480 	}
   2481 	ngep->io_regs = regs;
   2482 	ngep->progress |= PROGRESS_REGS;
   2483 
   2484 	err = nge_register_intrs_and_init_locks(ngep);
   2485 	if (err != DDI_SUCCESS) {
   2486 		nge_problem(ngep, "nge_attach:"
   2487 		    " register intrs and init locks failed");
   2488 		goto attach_fail;
   2489 	}
   2490 	nge_init_ring_param_lock(ngep);
   2491 	ngep->progress |= PROGRESS_INTR;
   2492 
   2493 	mutex_enter(ngep->genlock);
   2494 
   2495 	if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 ||
   2496 	    ngep->chipinfo.device == DEVICE_ID_MCP55_372) {
   2497 		err = nge_smu_sema(ngep, B_TRUE);
   2498 		if (err != DDI_SUCCESS) {
   2499 			nge_problem(ngep, "nge_attach: nge_smu_sema() failed");
   2500 			goto attach_fail;
   2501 		}
   2502 	}
   2503 	/*
   2504 	 * Initialise link state variables
   2505 	 * Stop, reset & reinitialise the chip.
   2506 	 * Initialise the (internal) PHY.
   2507 	 */
   2508 	nge_phys_init(ngep);
   2509 	ngep->nge_chip_state = NGE_CHIP_INITIAL;
   2510 	err = nge_chip_reset(ngep);
   2511 	if (err != DDI_SUCCESS) {
   2512 		nge_problem(ngep, "nge_attach: nge_chip_reset() failed");
   2513 		mutex_exit(ngep->genlock);
   2514 		goto attach_fail;
   2515 	}
   2516 	nge_chip_sync(ngep);
   2517 
   2518 	/*
   2519 	 * Now that mutex locks are initialized, enable interrupts.
   2520 	 */
   2521 	if (ngep->intr_cap & DDI_INTR_FLAG_BLOCK) {
   2522 		/* Call ddi_intr_block_enable() for MSI interrupts */
   2523 		(void) ddi_intr_block_enable(ngep->htable,
   2524 		    ngep->intr_actual_cnt);
   2525 	} else {
   2526 		/* Call ddi_intr_enable for MSI or FIXED interrupts */
   2527 		for (i = 0; i < ngep->intr_actual_cnt; i++) {
   2528 			(void) ddi_intr_enable(ngep->htable[i]);
   2529 		}
   2530 	}
   2531 
   2532 	ngep->link_state = LINK_STATE_UNKNOWN;
   2533 	ngep->progress |= PROGRESS_HWINT;
   2534 
   2535 	/*
   2536 	 * Register NDD-tweakable parameters
   2537 	 */
   2538 	if (nge_nd_init(ngep)) {
   2539 		nge_problem(ngep, "nge_attach: nge_nd_init() failed");
   2540 		mutex_exit(ngep->genlock);
   2541 		goto attach_fail;
   2542 	}
   2543 	ngep->progress |= PROGRESS_NDD;
   2544 
   2545 	/*
   2546 	 * Create & initialise named kstats
   2547 	 */
   2548 	nge_init_kstats(ngep, instance);
   2549 	ngep->progress |= PROGRESS_KSTATS;
   2550 
   2551 	mutex_exit(ngep->genlock);
   2552 
   2553 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
   2554 		goto attach_fail;
   2555 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
   2556 	macp->m_driver = ngep;
   2557 	macp->m_dip = devinfo;
   2558 	macp->m_src_addr = infop->vendor_addr.addr;
   2559 	macp->m_callbacks = &nge_m_callbacks;
   2560 	macp->m_min_sdu = 0;
   2561 	macp->m_max_sdu = ngep->default_mtu;
   2562 	macp->m_margin = VTAG_SIZE;
   2563 	macp->m_priv_props = nge_priv_props;
   2564 	macp->m_priv_prop_count = NGE_MAX_PRIV_PROPS;
   2565 	/*
   2566 	 * Finally, we're ready to register ourselves with the mac
   2567 	 * interface; if this succeeds, we're all ready to start()
   2568 	 */
   2569 	err = mac_register(macp, &ngep->mh);
   2570 	mac_free(macp);
   2571 	if (err != 0)
   2572 		goto attach_fail;
   2573 
   2574 	/*
   2575 	 * Register a periodical handler.
   2576 	 * nge_chip_cyclic() is invoked in kernel context.
   2577 	 */
   2578 	ngep->periodic_id = ddi_periodic_add(nge_chip_cyclic, ngep,
   2579 	    NGE_CYCLIC_PERIOD, DDI_IPL_0);
   2580 
   2581 	ngep->progress |= PROGRESS_READY;
   2582 	return (DDI_SUCCESS);
   2583 
   2584 attach_fail:
   2585 	nge_unattach(ngep);
   2586 	return (DDI_FAILURE);
   2587 }
   2588 
   2589 static int
   2590 nge_suspend(nge_t *ngep)
   2591 {
   2592 	mutex_enter(ngep->genlock);
   2593 	rw_enter(ngep->rwlock, RW_WRITER);
   2594 
   2595 	/* if the port hasn't been plumbed, just return */
   2596 	if (ngep->nge_mac_state != NGE_MAC_STARTED) {
   2597 		rw_exit(ngep->rwlock);
   2598 		mutex_exit(ngep->genlock);
   2599 		return (DDI_SUCCESS);
   2600 	}
   2601 	ngep->suspended = B_TRUE;
   2602 	(void) nge_chip_stop(ngep, B_FALSE);
   2603 	ngep->nge_mac_state = NGE_MAC_STOPPED;
   2604 
   2605 	rw_exit(ngep->rwlock);
   2606 	mutex_exit(ngep->genlock);
   2607 	return (DDI_SUCCESS);
   2608 }
   2609 
   2610 /*
   2611  * detach(9E) -- Detach a device from the system
   2612  */
   2613 static int
   2614 nge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
   2615 {
   2616 	int i;
   2617 	nge_t *ngep;
   2618 	mul_item *p, *nextp;
   2619 	buff_ring_t *brp;
   2620 
   2621 	NGE_GTRACE(("nge_detach($%p, %d)", (void *)devinfo, cmd));
   2622 
   2623 	ngep = ddi_get_driver_private(devinfo);
   2624 	brp = ngep->buff;
   2625 
   2626 	switch (cmd) {
   2627 	default:
   2628 		return (DDI_FAILURE);
   2629 
   2630 	case DDI_SUSPEND:
   2631 		/*
   2632 		 * Stop the NIC
   2633 		 * Note: This driver doesn't currently support WOL, but
   2634 		 *	should it in the future, it is important to
   2635 		 *	make sure the PHY remains powered so that the
   2636 		 *	wakeup packet can actually be recieved.
   2637 		 */
   2638 		return (nge_suspend(ngep));
   2639 
   2640 	case DDI_DETACH:
   2641 		break;
   2642 	}
   2643 
   2644 	/* Try to wait all the buffer post to upper layer be released */
   2645 	for (i = 0; i < 1000; i++) {
   2646 		if (brp->rx_hold == 0)
   2647 			break;
   2648 		drv_usecwait(1000);
   2649 	}
   2650 
   2651 	/* If there is any posted buffer, reject to detach */
   2652 	if (brp->rx_hold != 0)
   2653 		return (DDI_FAILURE);
   2654 
   2655 	/*
   2656 	 * Unregister from the GLD subsystem.  This can fail, in
   2657 	 * particular if there are DLPI style-2 streams still open -
   2658 	 * in which case we just return failure without shutting
   2659 	 * down chip operations.
   2660 	 */
   2661 	if (mac_unregister(ngep->mh) != DDI_SUCCESS)
   2662 		return (DDI_FAILURE);
   2663 
   2664 	/*
   2665 	 * Recycle the multicast table. mac_unregister() should be called
   2666 	 * before it to ensure the multicast table can be used even if
   2667 	 * mac_unregister() fails.
   2668 	 */
   2669 	for (p = ngep->pcur_mulist; p != NULL; p = nextp) {
   2670 		nextp = p->next;
   2671 		kmem_free(p, sizeof (mul_item));
   2672 	}
   2673 	ngep->pcur_mulist = NULL;
   2674 
   2675 	/*
   2676 	 * All activity stopped, so we can clean up & exit
   2677 	 */
   2678 	nge_unattach(ngep);
   2679 	return (DDI_SUCCESS);
   2680 }
   2681 
   2682 /*
   2683  * quiesce(9E) entry point.
   2684  *
   2685  * This function is called when the system is single-threaded at high
   2686  * PIL with preemption disabled. Therefore, this function must not be
   2687  * blocked.
   2688  *
   2689  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
   2690  * DDI_FAILURE indicates an error condition and should almost never happen.
   2691  */
   2692 static int
   2693 nge_quiesce(dev_info_t *devinfo)
   2694 {
   2695 	nge_t *ngep;
   2696 
   2697 	ngep = ddi_get_driver_private(devinfo);
   2698 
   2699 	if (ngep == NULL)
   2700 		return (DDI_FAILURE);
   2701 
   2702 	/*
   2703 	 * Turn off debug tracing
   2704 	 */
   2705 	nge_debug = 0;
   2706 	ngep->debug = 0;
   2707 
   2708 	nge_restore_mac_addr(ngep);
   2709 	(void) nge_chip_stop(ngep, B_FALSE);
   2710 
   2711 	return (DDI_SUCCESS);
   2712 }
   2713 
   2714 
   2715 
   2716 /*
   2717  * ========== Module Loading Data & Entry Points ==========
   2718  */
   2719 
   2720 DDI_DEFINE_STREAM_OPS(nge_dev_ops, nulldev, nulldev, nge_attach, nge_detach,
   2721     NULL, NULL, D_MP, NULL, nge_quiesce);
   2722 
   2723 
   2724 static struct modldrv nge_modldrv = {
   2725 	&mod_driverops,		/* Type of module.  This one is a driver */
   2726 	nge_ident,		/* short description */
   2727 	&nge_dev_ops		/* driver specific ops */
   2728 };
   2729 
   2730 static struct modlinkage modlinkage = {
   2731 	MODREV_1, (void *)&nge_modldrv, NULL
   2732 };
   2733 
   2734 
   2735 int
   2736 _info(struct modinfo *modinfop)
   2737 {
   2738 	return (mod_info(&modlinkage, modinfop));
   2739 }
   2740 
   2741 int
   2742 _init(void)
   2743 {
   2744 	int status;
   2745 
   2746 	mac_init_ops(&nge_dev_ops, "nge");
   2747 	status = mod_install(&modlinkage);
   2748 	if (status != DDI_SUCCESS)
   2749 		mac_fini_ops(&nge_dev_ops);
   2750 	else
   2751 		mutex_init(nge_log_mutex, NULL, MUTEX_DRIVER, NULL);
   2752 
   2753 	return (status);
   2754 }
   2755 
   2756 int
   2757 _fini(void)
   2758 {
   2759 	int status;
   2760 
   2761 	status = mod_remove(&modlinkage);
   2762 	if (status == DDI_SUCCESS) {
   2763 		mac_fini_ops(&nge_dev_ops);
   2764 		mutex_destroy(nge_log_mutex);
   2765 	}
   2766 
   2767 	return (status);
   2768 }
   2769 
   2770 /*
   2771  * ============ Init MSI/Fixed/SoftInterrupt routines ==============
   2772  */
   2773 
   2774 /*
   2775  * Register interrupts and initialize each mutex and condition variables
   2776  */
   2777 
   2778 static int
   2779 nge_register_intrs_and_init_locks(nge_t *ngep)
   2780 {
   2781 	int		err;
   2782 	int		intr_types;
   2783 	uint_t		soft_prip;
   2784 	nge_msi_mask	msi_mask;
   2785 	nge_msi_map0_vec map0_vec;
   2786 	nge_msi_map1_vec map1_vec;
   2787 
   2788 	/*
   2789 	 * Add the softint handlers:
   2790 	 *
   2791 	 * Both of these handlers are used to avoid restrictions on the
   2792 	 * context and/or mutexes required for some operations.  In
   2793 	 * particular, the hardware interrupt handler and its subfunctions
   2794 	 * can detect a number of conditions that we don't want to handle
   2795 	 * in that context or with that set of mutexes held.  So, these
   2796 	 * softints are triggered instead:
   2797 	 *
   2798 	 * the <resched> softint is triggered if if we have previously
   2799 	 * had to refuse to send a packet because of resource shortage
   2800 	 * (we've run out of transmit buffers), but the send completion
   2801 	 * interrupt handler has now detected that more buffers have
   2802 	 * become available.  Its only purpose is to call gld_sched()
   2803 	 * to retry the pending transmits (we're not allowed to hold
   2804 	 * driver-defined mutexes across gld_sched()).
   2805 	 *
   2806 	 * the <factotum> is triggered if the h/w interrupt handler
   2807 	 * sees the <link state changed> or <error> bits in the status
   2808 	 * block.  It's also triggered periodically to poll the link
   2809 	 * state, just in case we aren't getting link status change
   2810 	 * interrupts ...
   2811 	 */
   2812 	err = ddi_intr_add_softint(ngep->devinfo, &ngep->resched_hdl,
   2813 	    DDI_INTR_SOFTPRI_MIN, nge_reschedule, (caddr_t)ngep);
   2814 	if (err != DDI_SUCCESS) {
   2815 		nge_problem(ngep,
   2816 		    "nge_attach: add nge_reschedule softintr failed");
   2817 
   2818 		return (DDI_FAILURE);
   2819 	}
   2820 	ngep->progress |= PROGRESS_RESCHED;
   2821 	err = ddi_intr_add_softint(ngep->devinfo, &ngep->factotum_hdl,
   2822 	    DDI_INTR_SOFTPRI_MIN, nge_chip_factotum, (caddr_t)ngep);
   2823 	if (err != DDI_SUCCESS) {
   2824 		nge_problem(ngep,
   2825 		    "nge_attach: add nge_chip_factotum softintr failed!");
   2826 
   2827 		return (DDI_FAILURE);
   2828 	}
   2829 	if (ddi_intr_get_softint_pri(ngep->factotum_hdl, &soft_prip)
   2830 	    != DDI_SUCCESS) {
   2831 		nge_problem(ngep, "nge_attach: get softintr priority failed\n");
   2832 
   2833 		return (DDI_FAILURE);
   2834 	}
   2835 	ngep->soft_pri = soft_prip;
   2836 
   2837 	ngep->progress |= PROGRESS_FACTOTUM;
   2838 	/* Get supported interrupt types */
   2839 	if (ddi_intr_get_supported_types(ngep->devinfo, &intr_types)
   2840 	    != DDI_SUCCESS) {
   2841 		nge_error(ngep, "ddi_intr_get_supported_types failed\n");
   2842 
   2843 		return (DDI_FAILURE);
   2844 	}
   2845 
   2846 	NGE_DEBUG(("ddi_intr_get_supported_types() returned: %x",
   2847 	    intr_types));
   2848 
   2849 	if ((intr_types & DDI_INTR_TYPE_MSI) && nge_enable_msi) {
   2850 
   2851 		/* MSI Configurations for mcp55 chipset */
   2852 		if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 ||
   2853 		    ngep->chipinfo.device == DEVICE_ID_MCP55_372) {
   2854 
   2855 
   2856 			/* Enable the 8 vectors */
   2857 			msi_mask.msi_mask_val =
   2858 			    nge_reg_get32(ngep, NGE_MSI_MASK);
   2859 			msi_mask.msi_msk_bits.vec0 = NGE_SET;
   2860 			msi_mask.msi_msk_bits.vec1 = NGE_SET;
   2861 			msi_mask.msi_msk_bits.vec2 = NGE_SET;
   2862 			msi_mask.msi_msk_bits.vec3 = NGE_SET;
   2863 			msi_mask.msi_msk_bits.vec4 = NGE_SET;
   2864 			msi_mask.msi_msk_bits.vec5 = NGE_SET;
   2865 			msi_mask.msi_msk_bits.vec6 = NGE_SET;
   2866 			msi_mask.msi_msk_bits.vec7 = NGE_SET;
   2867 			nge_reg_put32(ngep, NGE_MSI_MASK,
   2868 			    msi_mask.msi_mask_val);
   2869 
   2870 			/*
   2871 			 * Remapping the MSI MAP0 and MAP1. MCP55
   2872 			 * is default mapping all the interrupt to 0 vector.
   2873 			 * Software needs to remapping this.
   2874 			 * This mapping is same as CK804.
   2875 			 */
   2876 			map0_vec.msi_map0_val =
   2877 			    nge_reg_get32(ngep, NGE_MSI_MAP0);
   2878 			map1_vec.msi_map1_val =
   2879 			    nge_reg_get32(ngep, NGE_MSI_MAP1);
   2880 			map0_vec.vecs_bits.reint_vec = 0;
   2881 			map0_vec.vecs_bits.rcint_vec = 0;
   2882 			map0_vec.vecs_bits.miss_vec = 3;
   2883 			map0_vec.vecs_bits.teint_vec = 5;
   2884 			map0_vec.vecs_bits.tcint_vec = 5;
   2885 			map0_vec.vecs_bits.stint_vec = 2;
   2886 			map0_vec.vecs_bits.mint_vec = 6;
   2887 			map0_vec.vecs_bits.rfint_vec = 0;
   2888 			map1_vec.vecs_bits.tfint_vec = 5;
   2889 			map1_vec.vecs_bits.feint_vec = 6;
   2890 			map1_vec.vecs_bits.resv8_11 = 3;
   2891 			map1_vec.vecs_bits.resv12_15 = 1;
   2892 			map1_vec.vecs_bits.resv16_19 = 0;
   2893 			map1_vec.vecs_bits.resv20_23 = 7;
   2894 			map1_vec.vecs_bits.resv24_31 = 0xff;
   2895 			nge_reg_put32(ngep, NGE_MSI_MAP0,
   2896 			    map0_vec.msi_map0_val);
   2897 			nge_reg_put32(ngep, NGE_MSI_MAP1,
   2898 			    map1_vec.msi_map1_val);
   2899 		}
   2900 		if (nge_add_intrs(ngep, DDI_INTR_TYPE_MSI) != DDI_SUCCESS) {
   2901 			NGE_DEBUG(("MSI registration failed, "
   2902 			    "trying FIXED interrupt type\n"));
   2903 		} else {
   2904 			nge_log(ngep, "Using MSI interrupt type\n");
   2905 
   2906 			ngep->intr_type = DDI_INTR_TYPE_MSI;
   2907 			ngep->progress |= PROGRESS_SWINT;
   2908 		}
   2909 	}
   2910 
   2911 	if (!(ngep->progress & PROGRESS_SWINT) &&
   2912 	    (intr_types & DDI_INTR_TYPE_FIXED)) {
   2913 		if (nge_add_intrs(ngep, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS) {
   2914 			nge_error(ngep, "FIXED interrupt "
   2915 			    "registration failed\n");
   2916 
   2917 			return (DDI_FAILURE);
   2918 		}
   2919 
   2920 		nge_log(ngep, "Using FIXED interrupt type\n");
   2921 
   2922 		ngep->intr_type = DDI_INTR_TYPE_FIXED;
   2923 		ngep->progress |= PROGRESS_SWINT;
   2924 	}
   2925 
   2926 
   2927 	if (!(ngep->progress & PROGRESS_SWINT)) {
   2928 		nge_error(ngep, "No interrupts registered\n");
   2929 
   2930 		return (DDI_FAILURE);
   2931 	}
   2932 	mutex_init(ngep->genlock, NULL, MUTEX_DRIVER,
   2933 	    DDI_INTR_PRI(ngep->intr_pri));
   2934 	mutex_init(ngep->softlock, NULL, MUTEX_DRIVER,
   2935 	    DDI_INTR_PRI(ngep->soft_pri));
   2936 	rw_init(ngep->rwlock, NULL, RW_DRIVER,
   2937 	    DDI_INTR_PRI(ngep->intr_pri));
   2938 
   2939 	return (DDI_SUCCESS);
   2940 }
   2941 
   2942 /*
   2943  * nge_add_intrs:
   2944  *
   2945  * Register FIXED or MSI interrupts.
   2946  */
   2947 static int
   2948 nge_add_intrs(nge_t *ngep, int	intr_type)
   2949 {
   2950 	dev_info_t	*dip = ngep->devinfo;
   2951 	int		avail, actual, intr_size, count = 0;
   2952 	int		i, flag, ret;
   2953 
   2954 	NGE_DEBUG(("nge_add_intrs: interrupt type 0x%x\n", intr_type));
   2955 
   2956 	/* Get number of interrupts */
   2957 	ret = ddi_intr_get_nintrs(dip, intr_type, &count);
   2958 	if ((ret != DDI_SUCCESS) || (count == 0)) {
   2959 		nge_error(ngep, "ddi_intr_get_nintrs() failure, ret: %d, "
   2960 		    "count: %d", ret, count);
   2961 
   2962 		return (DDI_FAILURE);
   2963 	}
   2964 
   2965 	/* Get number of available interrupts */
   2966 	ret = ddi_intr_get_navail(dip, intr_type, &avail);
   2967 	if ((ret != DDI_SUCCESS) || (avail == 0)) {
   2968 		nge_error(ngep, "ddi_intr_get_navail() failure, "
   2969 		    "ret: %d, avail: %d\n", ret, avail);
   2970 
   2971 		return (DDI_FAILURE);
   2972 	}
   2973 
   2974 	if (avail < count) {
   2975 		NGE_DEBUG(("nitrs() returned %d, navail returned %d\n",
   2976 		    count, avail));
   2977 	}
   2978 	flag = DDI_INTR_ALLOC_NORMAL;
   2979 
   2980 	/* Allocate an array of interrupt handles */
   2981 	intr_size = count * sizeof (ddi_intr_handle_t);
   2982 	ngep->htable = kmem_alloc(intr_size, KM_SLEEP);
   2983 
   2984 	/* Call ddi_intr_alloc() */
   2985 	ret = ddi_intr_alloc(dip, ngep->htable, intr_type, 0,
   2986 	    count, &actual, flag);
   2987 
   2988 	if ((ret != DDI_SUCCESS) || (actual == 0)) {
   2989 		nge_error(ngep, "ddi_intr_alloc() failed %d\n", ret);
   2990 
   2991 		kmem_free(ngep->htable, intr_size);
   2992 		return (DDI_FAILURE);
   2993 	}
   2994 
   2995 	if (actual < count) {
   2996 		NGE_DEBUG(("Requested: %d, Received: %d\n",
   2997 		    count, actual));
   2998 	}
   2999 
   3000 	ngep->intr_actual_cnt = actual;
   3001 	ngep->intr_req_cnt = count;
   3002 
   3003 	/*
   3004 	 * Get priority for first msi, assume remaining are all the same
   3005 	 */
   3006 	if ((ret = ddi_intr_get_pri(ngep->htable[0], &ngep->intr_pri)) !=
   3007 	    DDI_SUCCESS) {
   3008 		nge_error(ngep, "ddi_intr_get_pri() failed %d\n", ret);
   3009 
   3010 		/* Free already allocated intr */
   3011 		for (i = 0; i < actual; i++) {
   3012 			(void) ddi_intr_free(ngep->htable[i]);
   3013 		}
   3014 
   3015 		kmem_free(ngep->htable, intr_size);
   3016 
   3017 		return (DDI_FAILURE);
   3018 	}
   3019 	/* Test for high level mutex */
   3020 	if (ngep->intr_pri >= ddi_intr_get_hilevel_pri()) {
   3021 		nge_error(ngep, "nge_add_intrs:"
   3022 		    "Hi level interrupt not supported");
   3023 
   3024 		for (i = 0; i < actual; i++)
   3025 			(void) ddi_intr_free(ngep->htable[i]);
   3026 
   3027 		kmem_free(ngep->htable, intr_size);
   3028 
   3029 		return (DDI_FAILURE);
   3030 	}
   3031 
   3032 
   3033 	/* Call ddi_intr_add_handler() */
   3034 	for (i = 0; i < actual; i++) {
   3035 		if ((ret = ddi_intr_add_handler(ngep->htable[i], nge_chip_intr,
   3036 		    (caddr_t)ngep, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
   3037 			nge_error(ngep, "ddi_intr_add_handler() "
   3038 			    "failed %d\n", ret);
   3039 
   3040 			/* Free already allocated intr */
   3041 			for (i = 0; i < actual; i++) {
   3042 				(void) ddi_intr_free(ngep->htable[i]);
   3043 			}
   3044 
   3045 			kmem_free(ngep->htable, intr_size);
   3046 
   3047 			return (DDI_FAILURE);
   3048 		}
   3049 	}
   3050 
   3051 	if ((ret = ddi_intr_get_cap(ngep->htable[0], &ngep->intr_cap))
   3052 	    != DDI_SUCCESS) {
   3053 		nge_error(ngep, "ddi_intr_get_cap() failed %d\n", ret);
   3054 
   3055 		for (i = 0; i < actual; i++) {
   3056 			(void) ddi_intr_remove_handler(ngep->htable[i]);
   3057 			(void) ddi_intr_free(ngep->htable[i]);
   3058 		}
   3059 
   3060 		kmem_free(ngep->htable, intr_size);
   3061 
   3062 		return (DDI_FAILURE);
   3063 	}
   3064 
   3065 	return (DDI_SUCCESS);
   3066 }
   3067 
   3068 /*
   3069  * nge_rem_intrs:
   3070  *
   3071  * Unregister FIXED or MSI interrupts
   3072  */
   3073 static void
   3074 nge_rem_intrs(nge_t *ngep)
   3075 {
   3076 	int	i;
   3077 
   3078 	NGE_DEBUG(("nge_rem_intrs\n"));
   3079 
   3080 	/* Disable all interrupts */
   3081 	if (ngep->intr_cap & DDI_INTR_FLAG_BLOCK) {
   3082 		/* Call ddi_intr_block_disable() */
   3083 		(void) ddi_intr_block_disable(ngep->htable,
   3084 		    ngep->intr_actual_cnt);
   3085 	} else {
   3086 		for (i = 0; i < ngep->intr_actual_cnt; i++) {
   3087 			(void) ddi_intr_disable(ngep->htable[i]);
   3088 		}
   3089 	}
   3090 
   3091 	/* Call ddi_intr_remove_handler() */
   3092 	for (i = 0; i < ngep->intr_actual_cnt; i++) {
   3093 		(void) ddi_intr_remove_handler(ngep->htable[i]);
   3094 		(void) ddi_intr_free(ngep->htable[i]);
   3095 	}
   3096 
   3097 	kmem_free(ngep->htable,
   3098 	    ngep->intr_req_cnt * sizeof (ddi_intr_handle_t));
   3099 }
   3100