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