Home | History | Annotate | Download | only in nxge
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include <sys/nxge/nxge_impl.h>
     28 #include <sys/nxge/nxge_txdma.h>
     29 #include <sys/nxge/nxge_hio.h>
     30 #include <npi_tx_rd64.h>
     31 #include <npi_tx_wr64.h>
     32 #include <sys/llc1.h>
     33 
     34 uint32_t 	nxge_reclaim_pending = TXDMA_RECLAIM_PENDING_DEFAULT;
     35 uint32_t	nxge_tx_minfree = 64;
     36 uint32_t	nxge_tx_intr_thres = 0;
     37 uint32_t	nxge_tx_max_gathers = TX_MAX_GATHER_POINTERS;
     38 uint32_t	nxge_tx_tiny_pack = 1;
     39 uint32_t	nxge_tx_use_bcopy = 1;
     40 
     41 extern uint32_t 	nxge_tx_ring_size;
     42 extern uint32_t 	nxge_bcopy_thresh;
     43 extern uint32_t 	nxge_dvma_thresh;
     44 extern uint32_t 	nxge_dma_stream_thresh;
     45 extern dma_method_t 	nxge_force_dma;
     46 extern uint32_t		nxge_cksum_offload;
     47 
     48 /* Device register access attributes for PIO.  */
     49 extern ddi_device_acc_attr_t nxge_dev_reg_acc_attr;
     50 /* Device descriptor access attributes for DMA.  */
     51 extern ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr;
     52 /* Device buffer access attributes for DMA.  */
     53 extern ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr;
     54 extern ddi_dma_attr_t nxge_desc_dma_attr;
     55 extern ddi_dma_attr_t nxge_tx_dma_attr;
     56 
     57 extern void nxge_tx_ring_task(void *arg);
     58 
     59 static nxge_status_t nxge_map_txdma(p_nxge_t, int);
     60 
     61 static nxge_status_t nxge_txdma_hw_start(p_nxge_t, int);
     62 
     63 static nxge_status_t nxge_map_txdma_channel(p_nxge_t, uint16_t,
     64 	p_nxge_dma_common_t *, p_tx_ring_t *,
     65 	uint32_t, p_nxge_dma_common_t *,
     66 	p_tx_mbox_t *);
     67 static void nxge_unmap_txdma_channel(p_nxge_t, uint16_t);
     68 
     69 static nxge_status_t nxge_map_txdma_channel_buf_ring(p_nxge_t, uint16_t,
     70 	p_nxge_dma_common_t *, p_tx_ring_t *, uint32_t);
     71 static void nxge_unmap_txdma_channel_buf_ring(p_nxge_t, p_tx_ring_t);
     72 
     73 static void nxge_map_txdma_channel_cfg_ring(p_nxge_t, uint16_t,
     74 	p_nxge_dma_common_t *, p_tx_ring_t,
     75 	p_tx_mbox_t *);
     76 static void nxge_unmap_txdma_channel_cfg_ring(p_nxge_t,
     77 	p_tx_ring_t, p_tx_mbox_t);
     78 
     79 static nxge_status_t nxge_txdma_start_channel(p_nxge_t, uint16_t,
     80     p_tx_ring_t, p_tx_mbox_t);
     81 static nxge_status_t nxge_txdma_stop_channel(p_nxge_t, uint16_t);
     82 
     83 static p_tx_ring_t nxge_txdma_get_ring(p_nxge_t, uint16_t);
     84 static nxge_status_t nxge_tx_err_evnts(p_nxge_t, uint_t,
     85 	p_nxge_ldv_t, tx_cs_t);
     86 static p_tx_mbox_t nxge_txdma_get_mbox(p_nxge_t, uint16_t);
     87 static nxge_status_t nxge_txdma_fatal_err_recover(p_nxge_t,
     88 	uint16_t, p_tx_ring_t);
     89 
     90 static void nxge_txdma_fixup_hung_channel(p_nxge_t nxgep,
     91     p_tx_ring_t ring_p, uint16_t channel);
     92 
     93 nxge_status_t
     94 nxge_init_txdma_channels(p_nxge_t nxgep)
     95 {
     96 	nxge_grp_set_t	*set = &nxgep->tx_set;
     97 	int		i, tdc, count;
     98 	nxge_grp_t	*group;
     99 	dc_map_t	map;
    100 	int		dev_gindex;
    101 
    102 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_init_txdma_channels"));
    103 
    104 	for (i = 0, count = 0; i < NXGE_LOGICAL_GROUP_MAX; i++) {
    105 		if ((1 << i) & set->lg.map) {
    106 			group = set->group[i];
    107 			dev_gindex =
    108 			    nxgep->pt_config.hw_config.def_mac_txdma_grpid + i;
    109 			map = nxgep->pt_config.tdc_grps[dev_gindex].map;
    110 			for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
    111 				if ((1 << tdc) & map) {
    112 					if ((nxge_grp_dc_add(nxgep,
    113 					    group, VP_BOUND_TX, tdc)))
    114 						goto init_txdma_channels_exit;
    115 				}
    116 			}
    117 		}
    118 		if (++count == set->lg.count)
    119 			break;
    120 	}
    121 
    122 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_init_txdma_channels"));
    123 	return (NXGE_OK);
    124 
    125 init_txdma_channels_exit:
    126 	for (i = 0, count = 0; i < NXGE_LOGICAL_GROUP_MAX; i++) {
    127 		if ((1 << i) & set->lg.map) {
    128 			group = set->group[i];
    129 			dev_gindex =
    130 			    nxgep->pt_config.hw_config.def_mac_txdma_grpid + i;
    131 			map = nxgep->pt_config.tdc_grps[dev_gindex].map;
    132 			for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
    133 				if ((1 << tdc) & map) {
    134 					nxge_grp_dc_remove(nxgep,
    135 					    VP_BOUND_TX, tdc);
    136 				}
    137 			}
    138 		}
    139 		if (++count == set->lg.count)
    140 			break;
    141 	}
    142 
    143 	return (NXGE_ERROR);
    144 
    145 }
    146 
    147 nxge_status_t
    148 nxge_init_txdma_channel(
    149 	p_nxge_t nxge,
    150 	int channel)
    151 {
    152 	nxge_status_t status;
    153 
    154 	NXGE_DEBUG_MSG((nxge, MEM2_CTL, "==> nxge_init_txdma_channel"));
    155 
    156 	status = nxge_map_txdma(nxge, channel);
    157 	if (status != NXGE_OK) {
    158 		NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
    159 		    "<== nxge_init_txdma_channel: status 0x%x", status));
    160 		(void) npi_txdma_dump_tdc_regs(nxge->npi_handle, channel);
    161 		return (status);
    162 	}
    163 
    164 	status = nxge_txdma_hw_start(nxge, channel);
    165 	if (status != NXGE_OK) {
    166 		(void) nxge_unmap_txdma_channel(nxge, channel);
    167 		(void) npi_txdma_dump_tdc_regs(nxge->npi_handle, channel);
    168 		return (status);
    169 	}
    170 
    171 	if (!nxge->statsp->tdc_ksp[channel])
    172 		nxge_setup_tdc_kstats(nxge, channel);
    173 
    174 	NXGE_DEBUG_MSG((nxge, MEM2_CTL, "<== nxge_init_txdma_channel"));
    175 
    176 	return (status);
    177 }
    178 
    179 void
    180 nxge_uninit_txdma_channels(p_nxge_t nxgep)
    181 {
    182 	nxge_grp_set_t *set = &nxgep->tx_set;
    183 	int tdc;
    184 
    185 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_uninit_txdma_channels"));
    186 
    187 	if (set->owned.map == 0) {
    188 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
    189 		    "nxge_uninit_txdma_channels: no channels"));
    190 		return;
    191 	}
    192 
    193 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
    194 		if ((1 << tdc) & set->owned.map) {
    195 			nxge_grp_dc_remove(nxgep, VP_BOUND_TX, tdc);
    196 		}
    197 	}
    198 
    199 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_uninit_txdma_channels"));
    200 }
    201 
    202 void
    203 nxge_uninit_txdma_channel(p_nxge_t nxgep, int channel)
    204 {
    205 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_uninit_txdma_channel"));
    206 
    207 	if (nxgep->statsp->tdc_ksp[channel]) {
    208 		kstat_delete(nxgep->statsp->tdc_ksp[channel]);
    209 		nxgep->statsp->tdc_ksp[channel] = 0;
    210 	}
    211 
    212 	if (nxge_txdma_stop_channel(nxgep, channel) != NXGE_OK)
    213 		goto nxge_uninit_txdma_channel_exit;
    214 
    215 	nxge_unmap_txdma_channel(nxgep, channel);
    216 
    217 nxge_uninit_txdma_channel_exit:
    218 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_uninit_txdma_channel"));
    219 }
    220 
    221 void
    222 nxge_setup_dma_common(p_nxge_dma_common_t dest_p, p_nxge_dma_common_t src_p,
    223 	uint32_t entries, uint32_t size)
    224 {
    225 	size_t		tsize;
    226 	*dest_p = *src_p;
    227 	tsize = size * entries;
    228 	dest_p->alength = tsize;
    229 	dest_p->nblocks = entries;
    230 	dest_p->block_size = size;
    231 	dest_p->offset += tsize;
    232 
    233 	src_p->kaddrp = (caddr_t)dest_p->kaddrp + tsize;
    234 	src_p->alength -= tsize;
    235 	src_p->dma_cookie.dmac_laddress += tsize;
    236 	src_p->dma_cookie.dmac_size -= tsize;
    237 }
    238 
    239 /*
    240  * nxge_reset_txdma_channel
    241  *
    242  *	Reset a TDC.
    243  *
    244  * Arguments:
    245  * 	nxgep
    246  * 	channel		The channel to reset.
    247  * 	reg_data	The current TX_CS.
    248  *
    249  * Notes:
    250  *
    251  * NPI/NXGE function calls:
    252  *	npi_txdma_channel_reset()
    253  *	npi_txdma_channel_control()
    254  *
    255  * Registers accessed:
    256  *	TX_CS		DMC+0x40028 Transmit Control And Status
    257  *	TX_RING_KICK	DMC+0x40018 Transmit Ring Kick
    258  *
    259  * Context:
    260  *	Any domain
    261  */
    262 nxge_status_t
    263 nxge_reset_txdma_channel(p_nxge_t nxgep, uint16_t channel, uint64_t reg_data)
    264 {
    265 	npi_status_t		rs = NPI_SUCCESS;
    266 	nxge_status_t		status = NXGE_OK;
    267 	npi_handle_t		handle;
    268 
    269 	NXGE_DEBUG_MSG((nxgep, TX_CTL, " ==> nxge_reset_txdma_channel"));
    270 
    271 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
    272 	if ((reg_data & TX_CS_RST_MASK) == TX_CS_RST_MASK) {
    273 		rs = npi_txdma_channel_reset(handle, channel);
    274 	} else {
    275 		rs = npi_txdma_channel_control(handle, TXDMA_RESET,
    276 		    channel);
    277 	}
    278 
    279 	if (rs != NPI_SUCCESS) {
    280 		status = NXGE_ERROR | rs;
    281 	}
    282 
    283 	/*
    284 	 * Reset the tail (kick) register to 0.
    285 	 * (Hardware will not reset it. Tx overflow fatal
    286 	 * error if tail is not set to 0 after reset!
    287 	 */
    288 	TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0);
    289 
    290 	NXGE_DEBUG_MSG((nxgep, TX_CTL, " <== nxge_reset_txdma_channel"));
    291 	return (status);
    292 }
    293 
    294 /*
    295  * nxge_init_txdma_channel_event_mask
    296  *
    297  *	Enable interrupts for a set of events.
    298  *
    299  * Arguments:
    300  * 	nxgep
    301  * 	channel	The channel to map.
    302  * 	mask_p	The events to enable.
    303  *
    304  * Notes:
    305  *
    306  * NPI/NXGE function calls:
    307  *	npi_txdma_event_mask()
    308  *
    309  * Registers accessed:
    310  *	TX_ENT_MSK	DMC+0x40020 Transmit Event Mask
    311  *
    312  * Context:
    313  *	Any domain
    314  */
    315 nxge_status_t
    316 nxge_init_txdma_channel_event_mask(p_nxge_t nxgep, uint16_t channel,
    317 		p_tx_dma_ent_msk_t mask_p)
    318 {
    319 	npi_handle_t		handle;
    320 	npi_status_t		rs = NPI_SUCCESS;
    321 	nxge_status_t		status = NXGE_OK;
    322 
    323 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
    324 	    "<== nxge_init_txdma_channel_event_mask"));
    325 
    326 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
    327 	rs = npi_txdma_event_mask(handle, OP_SET, channel, mask_p);
    328 	if (rs != NPI_SUCCESS) {
    329 		status = NXGE_ERROR | rs;
    330 	}
    331 
    332 	return (status);
    333 }
    334 
    335 /*
    336  * nxge_init_txdma_channel_cntl_stat
    337  *
    338  *	Stop a TDC.  If at first we don't succeed, inject an error.
    339  *
    340  * Arguments:
    341  * 	nxgep
    342  * 	channel		The channel to stop.
    343  *
    344  * Notes:
    345  *
    346  * NPI/NXGE function calls:
    347  *	npi_txdma_control_status()
    348  *
    349  * Registers accessed:
    350  *	TX_CS		DMC+0x40028 Transmit Control And Status
    351  *
    352  * Context:
    353  *	Any domain
    354  */
    355 nxge_status_t
    356 nxge_init_txdma_channel_cntl_stat(p_nxge_t nxgep, uint16_t channel,
    357 	uint64_t reg_data)
    358 {
    359 	npi_handle_t		handle;
    360 	npi_status_t		rs = NPI_SUCCESS;
    361 	nxge_status_t		status = NXGE_OK;
    362 
    363 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
    364 	    "<== nxge_init_txdma_channel_cntl_stat"));
    365 
    366 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
    367 	rs = npi_txdma_control_status(handle, OP_SET, channel,
    368 	    (p_tx_cs_t)&reg_data);
    369 
    370 	if (rs != NPI_SUCCESS) {
    371 		status = NXGE_ERROR | rs;
    372 	}
    373 
    374 	return (status);
    375 }
    376 
    377 /*
    378  * nxge_enable_txdma_channel
    379  *
    380  *	Enable a TDC.
    381  *
    382  * Arguments:
    383  * 	nxgep
    384  * 	channel		The channel to enable.
    385  * 	tx_desc_p	channel's transmit descriptor ring.
    386  * 	mbox_p		channel's mailbox,
    387  *
    388  * Notes:
    389  *
    390  * NPI/NXGE function calls:
    391  *	npi_txdma_ring_config()
    392  *	npi_txdma_mbox_config()
    393  *	npi_txdma_channel_init_enable()
    394  *
    395  * Registers accessed:
    396  *	TX_RNG_CFIG	DMC+0x40000 Transmit Ring Configuration
    397  *	TXDMA_MBH	DMC+0x40030 TXDMA Mailbox High
    398  *	TXDMA_MBL	DMC+0x40038 TXDMA Mailbox Low
    399  *	TX_CS		DMC+0x40028 Transmit Control And Status
    400  *
    401  * Context:
    402  *	Any domain
    403  */
    404 nxge_status_t
    405 nxge_enable_txdma_channel(p_nxge_t nxgep,
    406 	uint16_t channel, p_tx_ring_t tx_desc_p, p_tx_mbox_t mbox_p)
    407 {
    408 	npi_handle_t		handle;
    409 	npi_status_t		rs = NPI_SUCCESS;
    410 	nxge_status_t		status = NXGE_OK;
    411 
    412 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_enable_txdma_channel"));
    413 
    414 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
    415 	/*
    416 	 * Use configuration data composed at init time.
    417 	 * Write to hardware the transmit ring configurations.
    418 	 */
    419 	rs = npi_txdma_ring_config(handle, OP_SET, channel,
    420 	    (uint64_t *)&(tx_desc_p->tx_ring_cfig.value));
    421 
    422 	if (rs != NPI_SUCCESS) {
    423 		return (NXGE_ERROR | rs);
    424 	}
    425 
    426 	if (isLDOMguest(nxgep)) {
    427 		/* Add interrupt handler for this channel. */
    428 		if (nxge_hio_intr_add(nxgep, VP_BOUND_TX, channel) != NXGE_OK)
    429 			return (NXGE_ERROR);
    430 	}
    431 
    432 	/* Write to hardware the mailbox */
    433 	rs = npi_txdma_mbox_config(handle, OP_SET, channel,
    434 	    (uint64_t *)&mbox_p->tx_mbox.dma_cookie.dmac_laddress);
    435 
    436 	if (rs != NPI_SUCCESS) {
    437 		return (NXGE_ERROR | rs);
    438 	}
    439 
    440 	/* Start the DMA engine. */
    441 	rs = npi_txdma_channel_init_enable(handle, channel);
    442 
    443 	if (rs != NPI_SUCCESS) {
    444 		return (NXGE_ERROR | rs);
    445 	}
    446 
    447 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_enable_txdma_channel"));
    448 
    449 	return (status);
    450 }
    451 
    452 void
    453 nxge_fill_tx_hdr(p_mblk_t mp, boolean_t fill_len,
    454 		boolean_t l4_cksum, int pkt_len, uint8_t npads,
    455 		p_tx_pkt_hdr_all_t pkthdrp,
    456 		t_uscalar_t start_offset,
    457 		t_uscalar_t stuff_offset)
    458 {
    459 	p_tx_pkt_header_t	hdrp;
    460 	p_mblk_t 		nmp;
    461 	uint64_t		tmp;
    462 	size_t 			mblk_len;
    463 	size_t 			iph_len;
    464 	size_t 			hdrs_size;
    465 	uint8_t			hdrs_buf[sizeof (struct ether_header) +
    466 	    64 + sizeof (uint32_t)];
    467 	uint8_t			*cursor;
    468 	uint8_t 		*ip_buf;
    469 	uint16_t		eth_type;
    470 	uint8_t			ipproto;
    471 	boolean_t		is_vlan = B_FALSE;
    472 	size_t			eth_hdr_size;
    473 
    474 	NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: mp $%p", mp));
    475 
    476 	/*
    477 	 * Caller should zero out the headers first.
    478 	 */
    479 	hdrp = (p_tx_pkt_header_t)&pkthdrp->pkthdr;
    480 
    481 	if (fill_len) {
    482 		NXGE_DEBUG_MSG((NULL, TX_CTL,
    483 		    "==> nxge_fill_tx_hdr: pkt_len %d "
    484 		    "npads %d", pkt_len, npads));
    485 		tmp = (uint64_t)pkt_len;
    486 		hdrp->value |= (tmp << TX_PKT_HEADER_TOT_XFER_LEN_SHIFT);
    487 		goto fill_tx_header_done;
    488 	}
    489 
    490 	hdrp->value |= (((uint64_t)npads) << TX_PKT_HEADER_PAD_SHIFT);
    491 
    492 	/*
    493 	 * mp is the original data packet (does not include the
    494 	 * Neptune transmit header).
    495 	 */
    496 	nmp = mp;
    497 	NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: "
    498 	    "mp $%p b_rptr $%p len %d",
    499 	    mp, nmp->b_rptr, MBLKL(nmp)));
    500 	/* copy ether_header from mblk to hdrs_buf */
    501 	cursor = &hdrs_buf[0];
    502 	tmp = sizeof (struct ether_vlan_header);
    503 	while ((nmp != NULL) && (tmp > 0)) {
    504 		size_t buflen;
    505 		mblk_len = MBLKL(nmp);
    506 		buflen = min((size_t)tmp, mblk_len);
    507 		bcopy(nmp->b_rptr, cursor, buflen);
    508 		cursor += buflen;
    509 		tmp -= buflen;
    510 		nmp = nmp->b_cont;
    511 	}
    512 
    513 	nmp = mp;
    514 	mblk_len = MBLKL(nmp);
    515 	ip_buf = NULL;
    516 	eth_type = ntohs(((p_ether_header_t)hdrs_buf)->ether_type);
    517 	NXGE_DEBUG_MSG((NULL, TX_CTL, "==> : nxge_fill_tx_hdr: (value 0x%llx) "
    518 	    "ether type 0x%x", eth_type, hdrp->value));
    519 
    520 	if (eth_type < ETHERMTU) {
    521 		tmp = 1ull;
    522 		hdrp->value |= (tmp << TX_PKT_HEADER_LLC_SHIFT);
    523 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: LLC "
    524 		    "value 0x%llx", hdrp->value));
    525 		if (*(hdrs_buf + sizeof (struct ether_header))
    526 		    == LLC_SNAP_SAP) {
    527 			eth_type = ntohs(*((uint16_t *)(hdrs_buf +
    528 			    sizeof (struct ether_header) + 6)));
    529 			NXGE_DEBUG_MSG((NULL, TX_CTL,
    530 			    "==> nxge_tx_pkt_hdr_init: LLC ether type 0x%x",
    531 			    eth_type));
    532 		} else {
    533 			goto fill_tx_header_done;
    534 		}
    535 	} else if (eth_type == VLAN_ETHERTYPE) {
    536 		tmp = 1ull;
    537 		hdrp->value |= (tmp << TX_PKT_HEADER_VLAN__SHIFT);
    538 
    539 		eth_type = ntohs(((struct ether_vlan_header *)
    540 		    hdrs_buf)->ether_type);
    541 		is_vlan = B_TRUE;
    542 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: VLAN "
    543 		    "value 0x%llx", hdrp->value));
    544 	}
    545 
    546 	if (!is_vlan) {
    547 		eth_hdr_size = sizeof (struct ether_header);
    548 	} else {
    549 		eth_hdr_size = sizeof (struct ether_vlan_header);
    550 	}
    551 
    552 	switch (eth_type) {
    553 	case ETHERTYPE_IP:
    554 		if (mblk_len > eth_hdr_size + sizeof (uint8_t)) {
    555 			ip_buf = nmp->b_rptr + eth_hdr_size;
    556 			mblk_len -= eth_hdr_size;
    557 			iph_len = ((*ip_buf) & 0x0f);
    558 			if (mblk_len > (iph_len + sizeof (uint32_t))) {
    559 				ip_buf = nmp->b_rptr;
    560 				ip_buf += eth_hdr_size;
    561 			} else {
    562 				ip_buf = NULL;
    563 			}
    564 
    565 		}
    566 		if (ip_buf == NULL) {
    567 			hdrs_size = 0;
    568 			((p_ether_header_t)hdrs_buf)->ether_type = 0;
    569 			while ((nmp) && (hdrs_size <
    570 			    sizeof (hdrs_buf))) {
    571 				mblk_len = (size_t)nmp->b_wptr -
    572 				    (size_t)nmp->b_rptr;
    573 				if (mblk_len >=
    574 				    (sizeof (hdrs_buf) - hdrs_size))
    575 					mblk_len = sizeof (hdrs_buf) -
    576 					    hdrs_size;
    577 				bcopy(nmp->b_rptr,
    578 				    &hdrs_buf[hdrs_size], mblk_len);
    579 				hdrs_size += mblk_len;
    580 				nmp = nmp->b_cont;
    581 			}
    582 			ip_buf = hdrs_buf;
    583 			ip_buf += eth_hdr_size;
    584 			iph_len = ((*ip_buf) & 0x0f);
    585 		}
    586 
    587 		ipproto = ip_buf[9];
    588 
    589 		tmp = (uint64_t)iph_len;
    590 		hdrp->value |= (tmp << TX_PKT_HEADER_IHL_SHIFT);
    591 		tmp = (uint64_t)(eth_hdr_size >> 1);
    592 		hdrp->value |= (tmp << TX_PKT_HEADER_L3START_SHIFT);
    593 
    594 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: IPv4 "
    595 		    " iph_len %d l3start %d eth_hdr_size %d proto 0x%x"
    596 		    "tmp 0x%x",
    597 		    iph_len, hdrp->bits.hdw.l3start, eth_hdr_size,
    598 		    ipproto, tmp));
    599 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: IP "
    600 		    "value 0x%llx", hdrp->value));
    601 
    602 		break;
    603 
    604 	case ETHERTYPE_IPV6:
    605 		hdrs_size = 0;
    606 		((p_ether_header_t)hdrs_buf)->ether_type = 0;
    607 		while ((nmp) && (hdrs_size <
    608 		    sizeof (hdrs_buf))) {
    609 			mblk_len = (size_t)nmp->b_wptr - (size_t)nmp->b_rptr;
    610 			if (mblk_len >=
    611 			    (sizeof (hdrs_buf) - hdrs_size))
    612 				mblk_len = sizeof (hdrs_buf) -
    613 				    hdrs_size;
    614 			bcopy(nmp->b_rptr,
    615 			    &hdrs_buf[hdrs_size], mblk_len);
    616 			hdrs_size += mblk_len;
    617 			nmp = nmp->b_cont;
    618 		}
    619 		ip_buf = hdrs_buf;
    620 		ip_buf += eth_hdr_size;
    621 
    622 		tmp = 1ull;
    623 		hdrp->value |= (tmp << TX_PKT_HEADER_IP_VER_SHIFT);
    624 
    625 		tmp = (eth_hdr_size >> 1);
    626 		hdrp->value |= (tmp << TX_PKT_HEADER_L3START_SHIFT);
    627 
    628 		/* byte 6 is the next header protocol */
    629 		ipproto = ip_buf[6];
    630 
    631 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: IPv6 "
    632 		    " iph_len %d l3start %d eth_hdr_size %d proto 0x%x",
    633 		    iph_len, hdrp->bits.hdw.l3start, eth_hdr_size,
    634 		    ipproto));
    635 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: IPv6 "
    636 		    "value 0x%llx", hdrp->value));
    637 
    638 		break;
    639 
    640 	default:
    641 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: non-IP"));
    642 		goto fill_tx_header_done;
    643 	}
    644 
    645 	switch (ipproto) {
    646 	case IPPROTO_TCP:
    647 		NXGE_DEBUG_MSG((NULL, TX_CTL,
    648 		    "==> nxge_fill_tx_hdr: TCP (cksum flag %d)", l4_cksum));
    649 		if (l4_cksum) {
    650 			hdrp->value |= TX_CKSUM_EN_PKT_TYPE_TCP;
    651 			hdrp->value |=
    652 			    (((uint64_t)(start_offset >> 1)) <<
    653 			    TX_PKT_HEADER_L4START_SHIFT);
    654 			hdrp->value |=
    655 			    (((uint64_t)(stuff_offset >> 1)) <<
    656 			    TX_PKT_HEADER_L4STUFF_SHIFT);
    657 
    658 			NXGE_DEBUG_MSG((NULL, TX_CTL,
    659 			    "==> nxge_tx_pkt_hdr_init: TCP CKSUM "
    660 			    "value 0x%llx", hdrp->value));
    661 		}
    662 
    663 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: TCP "
    664 		    "value 0x%llx", hdrp->value));
    665 		break;
    666 
    667 	case IPPROTO_UDP:
    668 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: UDP"));
    669 		if (l4_cksum) {
    670 			if (!nxge_cksum_offload) {
    671 				uint16_t	*up;
    672 				uint16_t	cksum;
    673 				t_uscalar_t	stuff_len;
    674 
    675 				/*
    676 				 * The checksum field has the
    677 				 * partial checksum.
    678 				 * IP_CSUM() macro calls ip_cksum() which
    679 				 * can add in the partial checksum.
    680 				 */
    681 				cksum = IP_CSUM(mp, start_offset, 0);
    682 				stuff_len = stuff_offset;
    683 				nmp = mp;
    684 				mblk_len = MBLKL(nmp);
    685 				while ((nmp != NULL) &&
    686 				    (mblk_len < stuff_len)) {
    687 					stuff_len -= mblk_len;
    688 					nmp = nmp->b_cont;
    689 					if (nmp)
    690 						mblk_len = MBLKL(nmp);
    691 				}
    692 				ASSERT(nmp);
    693 				up = (uint16_t *)(nmp->b_rptr + stuff_len);
    694 
    695 				*up = cksum;
    696 				hdrp->value &= ~TX_CKSUM_EN_PKT_TYPE_UDP;
    697 				NXGE_DEBUG_MSG((NULL, TX_CTL,
    698 				    "==> nxge_tx_pkt_hdr_init: UDP offset %d "
    699 				    "use sw cksum "
    700 				    "write to $%p cksum 0x%x content up 0x%x",
    701 				    stuff_len,
    702 				    up,
    703 				    cksum,
    704 				    *up));
    705 			} else {
    706 				/* Hardware will compute the full checksum */
    707 				hdrp->value |= TX_CKSUM_EN_PKT_TYPE_UDP;
    708 				hdrp->value |=
    709 				    (((uint64_t)(start_offset >> 1)) <<
    710 				    TX_PKT_HEADER_L4START_SHIFT);
    711 				hdrp->value |=
    712 				    (((uint64_t)(stuff_offset >> 1)) <<
    713 				    TX_PKT_HEADER_L4STUFF_SHIFT);
    714 
    715 				NXGE_DEBUG_MSG((NULL, TX_CTL,
    716 				    "==> nxge_tx_pkt_hdr_init: UDP offset %d "
    717 				    " use partial checksum "
    718 				    "cksum 0x%x ",
    719 				    "value 0x%llx",
    720 				    stuff_offset,
    721 				    IP_CSUM(mp, start_offset, 0),
    722 				    hdrp->value));
    723 			}
    724 		}
    725 
    726 		NXGE_DEBUG_MSG((NULL, TX_CTL,
    727 		    "==> nxge_tx_pkt_hdr_init: UDP"
    728 		    "value 0x%llx", hdrp->value));
    729 		break;
    730 
    731 	default:
    732 		goto fill_tx_header_done;
    733 	}
    734 
    735 fill_tx_header_done:
    736 	NXGE_DEBUG_MSG((NULL, TX_CTL,
    737 	    "==> nxge_fill_tx_hdr: pkt_len %d  "
    738 	    "npads %d value 0x%llx", pkt_len, npads, hdrp->value));
    739 
    740 	NXGE_DEBUG_MSG((NULL, TX_CTL, "<== nxge_fill_tx_hdr"));
    741 }
    742 
    743 /*ARGSUSED*/
    744 p_mblk_t
    745 nxge_tx_pkt_header_reserve(p_mblk_t mp, uint8_t *npads)
    746 {
    747 	p_mblk_t 		newmp = NULL;
    748 
    749 	if ((newmp = allocb(TX_PKT_HEADER_SIZE, BPRI_MED)) == NULL) {
    750 		NXGE_DEBUG_MSG((NULL, TX_CTL,
    751 		    "<== nxge_tx_pkt_header_reserve: allocb failed"));
    752 		return (NULL);
    753 	}
    754 
    755 	NXGE_DEBUG_MSG((NULL, TX_CTL,
    756 	    "==> nxge_tx_pkt_header_reserve: get new mp"));
    757 	DB_TYPE(newmp) = M_DATA;
    758 	newmp->b_rptr = newmp->b_wptr = DB_LIM(newmp);
    759 	linkb(newmp, mp);
    760 	newmp->b_rptr -= TX_PKT_HEADER_SIZE;
    761 
    762 	NXGE_DEBUG_MSG((NULL, TX_CTL, "==>nxge_tx_pkt_header_reserve: "
    763 	    "b_rptr $%p b_wptr $%p",
    764 	    newmp->b_rptr, newmp->b_wptr));
    765 
    766 	NXGE_DEBUG_MSG((NULL, TX_CTL,
    767 	    "<== nxge_tx_pkt_header_reserve: use new mp"));
    768 
    769 	return (newmp);
    770 }
    771 
    772 int
    773 nxge_tx_pkt_nmblocks(p_mblk_t mp, int *tot_xfer_len_p)
    774 {
    775 	uint_t 			nmblks;
    776 	ssize_t			len;
    777 	uint_t 			pkt_len;
    778 	p_mblk_t 		nmp, bmp, tmp;
    779 	uint8_t 		*b_wptr;
    780 
    781 	NXGE_DEBUG_MSG((NULL, TX_CTL,
    782 	    "==> nxge_tx_pkt_nmblocks: mp $%p rptr $%p wptr $%p "
    783 	    "len %d", mp, mp->b_rptr, mp->b_wptr, MBLKL(mp)));
    784 
    785 	nmp = mp;
    786 	bmp = mp;
    787 	nmblks = 0;
    788 	pkt_len = 0;
    789 	*tot_xfer_len_p = 0;
    790 
    791 	while (nmp) {
    792 		len = MBLKL(nmp);
    793 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_nmblocks: "
    794 		    "len %d pkt_len %d nmblks %d tot_xfer_len %d",
    795 		    len, pkt_len, nmblks,
    796 		    *tot_xfer_len_p));
    797 
    798 		if (len <= 0) {
    799 			bmp = nmp;
    800 			nmp = nmp->b_cont;
    801 			NXGE_DEBUG_MSG((NULL, TX_CTL,
    802 			    "==> nxge_tx_pkt_nmblocks: "
    803 			    "len (0) pkt_len %d nmblks %d",
    804 			    pkt_len, nmblks));
    805 			continue;
    806 		}
    807 
    808 		*tot_xfer_len_p += len;
    809 		NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_nmblocks: "
    810 		    "len %d pkt_len %d nmblks %d tot_xfer_len %d",
    811 		    len, pkt_len, nmblks,
    812 		    *tot_xfer_len_p));
    813 
    814 		if (len < nxge_bcopy_thresh) {
    815 			NXGE_DEBUG_MSG((NULL, TX_CTL,
    816 			    "==> nxge_tx_pkt_nmblocks: "
    817 			    "len %d (< thresh) pkt_len %d nmblks %d",
    818 			    len, pkt_len, nmblks));
    819 			if (pkt_len == 0)
    820 				nmblks++;
    821 			pkt_len += len;
    822 			if (pkt_len >= nxge_bcopy_thresh) {
    823 				pkt_len = 0;
    824 				len = 0;
    825 				nmp = bmp;
    826 			}
    827 		} else {
    828 			NXGE_DEBUG_MSG((NULL, TX_CTL,
    829 			    "==> nxge_tx_pkt_nmblocks: "
    830 			    "len %d (> thresh) pkt_len %d nmblks %d",
    831 			    len, pkt_len, nmblks));
    832 			pkt_len = 0;
    833 			nmblks++;
    834 			/*
    835 			 * Hardware limits the transfer length to 4K.
    836 			 * If len is more than 4K, we need to break
    837 			 * it up to at most 2 more blocks.
    838 			 */
    839 			if (len > TX_MAX_TRANSFER_LENGTH) {
    840 				uint32_t	nsegs;
    841 
    842 				nsegs = 1;
    843 				NXGE_DEBUG_MSG((NULL, TX_CTL,
    844 				    "==> nxge_tx_pkt_nmblocks: "
    845 				    "len %d pkt_len %d nmblks %d nsegs %d",
    846 				    len, pkt_len, nmblks, nsegs));
    847 				if (len % (TX_MAX_TRANSFER_LENGTH * 2)) {
    848 					++nsegs;
    849 				}
    850 				do {
    851 					b_wptr = nmp->b_rptr +
    852 					    TX_MAX_TRANSFER_LENGTH;
    853 					nmp->b_wptr = b_wptr;
    854 					if ((tmp = dupb(nmp)) == NULL) {
    855 						return (0);
    856 					}
    857 					tmp->b_rptr = b_wptr;
    858 					tmp->b_wptr = nmp->b_wptr;
    859 					tmp->b_cont = nmp->b_cont;
    860 					nmp->b_cont = tmp;
    861 					nmblks++;
    862 					if (--nsegs) {
    863 						nmp = tmp;
    864 					}
    865 				} while (nsegs);
    866 				nmp = tmp;
    867 			}
    868 		}
    869 
    870 		/*
    871 		 * Hardware limits the transmit gather pointers to 15.
    872 		 */
    873 		if (nmp->b_cont && (nmblks + TX_GATHER_POINTERS_THRESHOLD) >
    874 		    TX_MAX_GATHER_POINTERS) {
    875 			NXGE_DEBUG_MSG((NULL, TX_CTL,
    876 			    "==> nxge_tx_pkt_nmblocks: pull msg - "
    877 			    "len %d pkt_len %d nmblks %d",
    878 			    len, pkt_len, nmblks));
    879 			/* Pull all message blocks from b_cont */
    880 			if ((tmp = msgpullup(nmp->b_cont, -1)) == NULL) {
    881 				return (0);
    882 			}
    883 			freemsg(nmp->b_cont);
    884 			nmp->b_cont = tmp;
    885 			pkt_len = 0;
    886 		}
    887 		bmp = nmp;
    888 		nmp = nmp->b_cont;
    889 	}
    890 
    891 	NXGE_DEBUG_MSG((NULL, TX_CTL,
    892 	    "<== nxge_tx_pkt_nmblocks: rptr $%p wptr $%p "
    893 	    "nmblks %d len %d tot_xfer_len %d",
    894 	    mp->b_rptr, mp->b_wptr, nmblks,
    895 	    MBLKL(mp), *tot_xfer_len_p));
    896 
    897 	return (nmblks);
    898 }
    899 
    900 boolean_t
    901 nxge_txdma_reclaim(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, int nmblks)
    902 {
    903 	boolean_t 		status = B_TRUE;
    904 	p_nxge_dma_common_t	tx_desc_dma_p;
    905 	nxge_dma_common_t	desc_area;
    906 	p_tx_desc_t 		tx_desc_ring_vp;
    907 	p_tx_desc_t 		tx_desc_p;
    908 	p_tx_desc_t 		tx_desc_pp;
    909 	tx_desc_t 		r_tx_desc;
    910 	p_tx_msg_t 		tx_msg_ring;
    911 	p_tx_msg_t 		tx_msg_p;
    912 	npi_handle_t		handle;
    913 	tx_ring_hdl_t		tx_head;
    914 	uint32_t 		pkt_len;
    915 	uint_t			tx_rd_index;
    916 	uint16_t		head_index, tail_index;
    917 	uint8_t			tdc;
    918 	boolean_t		head_wrap, tail_wrap;
    919 	p_nxge_tx_ring_stats_t tdc_stats;
    920 	int			rc;
    921 
    922 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_reclaim"));
    923 
    924 	status = ((tx_ring_p->descs_pending < nxge_reclaim_pending) &&
    925 	    (nmblks != 0));
    926 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
    927 	    "==> nxge_txdma_reclaim: pending %d  reclaim %d nmblks %d",
    928 	    tx_ring_p->descs_pending, nxge_reclaim_pending,
    929 	    nmblks));
    930 	if (!status) {
    931 		tx_desc_dma_p = &tx_ring_p->tdc_desc;
    932 		desc_area = tx_ring_p->tdc_desc;
    933 		handle = NXGE_DEV_NPI_HANDLE(nxgep);
    934 		tx_desc_ring_vp = tx_desc_dma_p->kaddrp;
    935 		tx_desc_ring_vp =
    936 		    (p_tx_desc_t)DMA_COMMON_VPTR(desc_area);
    937 		tx_rd_index = tx_ring_p->rd_index;
    938 		tx_desc_p = &tx_desc_ring_vp[tx_rd_index];
    939 		tx_msg_ring = tx_ring_p->tx_msg_ring;
    940 		tx_msg_p = &tx_msg_ring[tx_rd_index];
    941 		tdc = tx_ring_p->tdc;
    942 		tdc_stats = tx_ring_p->tdc_stats;
    943 		if (tx_ring_p->descs_pending > tdc_stats->tx_max_pend) {
    944 			tdc_stats->tx_max_pend = tx_ring_p->descs_pending;
    945 		}
    946 
    947 		tail_index = tx_ring_p->wr_index;
    948 		tail_wrap = tx_ring_p->wr_index_wrap;
    949 
    950 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
    951 		    "==> nxge_txdma_reclaim: tdc %d tx_rd_index %d "
    952 		    "tail_index %d tail_wrap %d "
    953 		    "tx_desc_p $%p ($%p) ",
    954 		    tdc, tx_rd_index, tail_index, tail_wrap,
    955 		    tx_desc_p, (*(uint64_t *)tx_desc_p)));
    956 		/*
    957 		 * Read the hardware maintained transmit head
    958 		 * and wrap around bit.
    959 		 */
    960 		TXDMA_REG_READ64(handle, TX_RING_HDL_REG, tdc, &tx_head.value);
    961 		head_index =  tx_head.bits.ldw.head;
    962 		head_wrap = tx_head.bits.ldw.wrap;
    963 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
    964 		    "==> nxge_txdma_reclaim: "
    965 		    "tx_rd_index %d tail %d tail_wrap %d "
    966 		    "head %d wrap %d",
    967 		    tx_rd_index, tail_index, tail_wrap,
    968 		    head_index, head_wrap));
    969 
    970 		if (head_index == tail_index) {
    971 			if (TXDMA_RING_EMPTY(head_index, head_wrap,
    972 			    tail_index, tail_wrap) &&
    973 			    (head_index == tx_rd_index)) {
    974 				NXGE_DEBUG_MSG((nxgep, TX_CTL,
    975 				    "==> nxge_txdma_reclaim: EMPTY"));
    976 				return (B_TRUE);
    977 			}
    978 
    979 			NXGE_DEBUG_MSG((nxgep, TX_CTL,
    980 			    "==> nxge_txdma_reclaim: Checking "
    981 			    "if ring full"));
    982 			if (TXDMA_RING_FULL(head_index, head_wrap, tail_index,
    983 			    tail_wrap)) {
    984 				NXGE_DEBUG_MSG((nxgep, TX_CTL,
    985 				    "==> nxge_txdma_reclaim: full"));
    986 				return (B_FALSE);
    987 			}
    988 		}
    989 
    990 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
    991 		    "==> nxge_txdma_reclaim: tx_rd_index and head_index"));
    992 
    993 		tx_desc_pp = &r_tx_desc;
    994 		while ((tx_rd_index != head_index) &&
    995 		    (tx_ring_p->descs_pending != 0)) {
    996 
    997 			NXGE_DEBUG_MSG((nxgep, TX_CTL,
    998 			    "==> nxge_txdma_reclaim: Checking if pending"));
    999 
   1000 			NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1001 			    "==> nxge_txdma_reclaim: "
   1002 			    "descs_pending %d ",
   1003 			    tx_ring_p->descs_pending));
   1004 
   1005 			NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1006 			    "==> nxge_txdma_reclaim: "
   1007 			    "(tx_rd_index %d head_index %d "
   1008 			    "(tx_desc_p $%p)",
   1009 			    tx_rd_index, head_index,
   1010 			    tx_desc_p));
   1011 
   1012 			tx_desc_pp->value = tx_desc_p->value;
   1013 			NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1014 			    "==> nxge_txdma_reclaim: "
   1015 			    "(tx_rd_index %d head_index %d "
   1016 			    "tx_desc_p $%p (desc value 0x%llx) ",
   1017 			    tx_rd_index, head_index,
   1018 			    tx_desc_pp, (*(uint64_t *)tx_desc_pp)));
   1019 
   1020 			NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1021 			    "==> nxge_txdma_reclaim: dump desc:"));
   1022 
   1023 			pkt_len = tx_desc_pp->bits.hdw.tr_len;
   1024 			tdc_stats->obytes += pkt_len;
   1025 			tdc_stats->opackets += tx_desc_pp->bits.hdw.sop;
   1026 			NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1027 			    "==> nxge_txdma_reclaim: pkt_len %d "
   1028 			    "tdc channel %d opackets %d",
   1029 			    pkt_len,
   1030 			    tdc,
   1031 			    tdc_stats->opackets));
   1032 
   1033 			if (tx_msg_p->flags.dma_type == USE_DVMA) {
   1034 				NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1035 				    "tx_desc_p = $%p "
   1036 				    "tx_desc_pp = $%p "
   1037 				    "index = %d",
   1038 				    tx_desc_p,
   1039 				    tx_desc_pp,
   1040 				    tx_ring_p->rd_index));
   1041 				(void) dvma_unload(tx_msg_p->dvma_handle,
   1042 				    0, -1);
   1043 				tx_msg_p->dvma_handle = NULL;
   1044 				if (tx_ring_p->dvma_wr_index ==
   1045 				    tx_ring_p->dvma_wrap_mask) {
   1046 					tx_ring_p->dvma_wr_index = 0;
   1047 				} else {
   1048 					tx_ring_p->dvma_wr_index++;
   1049 				}
   1050 				tx_ring_p->dvma_pending--;
   1051 			} else if (tx_msg_p->flags.dma_type ==
   1052 			    USE_DMA) {
   1053 				NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1054 				    "==> nxge_txdma_reclaim: "
   1055 				    "USE DMA"));
   1056 				if (rc = ddi_dma_unbind_handle
   1057 				    (tx_msg_p->dma_handle)) {
   1058 					cmn_err(CE_WARN, "!nxge_reclaim: "
   1059 					    "ddi_dma_unbind_handle "
   1060 					    "failed. status %d", rc);
   1061 				}
   1062 			}
   1063 			NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1064 			    "==> nxge_txdma_reclaim: count packets"));
   1065 			/*
   1066 			 * count a chained packet only once.
   1067 			 */
   1068 			if (tx_msg_p->tx_message != NULL) {
   1069 				freemsg(tx_msg_p->tx_message);
   1070 				tx_msg_p->tx_message = NULL;
   1071 			}
   1072 
   1073 			tx_msg_p->flags.dma_type = USE_NONE;
   1074 			tx_rd_index = tx_ring_p->rd_index;
   1075 			tx_rd_index = (tx_rd_index + 1) &
   1076 			    tx_ring_p->tx_wrap_mask;
   1077 			tx_ring_p->rd_index = tx_rd_index;
   1078 			tx_ring_p->descs_pending--;
   1079 			tx_desc_p = &tx_desc_ring_vp[tx_rd_index];
   1080 			tx_msg_p = &tx_msg_ring[tx_rd_index];
   1081 		}
   1082 
   1083 		status = (nmblks <= ((int)tx_ring_p->tx_ring_size -
   1084 		    (int)tx_ring_p->descs_pending - TX_FULL_MARK));
   1085 		if (status) {
   1086 			(void) cas32((uint32_t *)&tx_ring_p->queueing, 1, 0);
   1087 		}
   1088 	} else {
   1089 		status = (nmblks <= ((int)tx_ring_p->tx_ring_size -
   1090 		    (int)tx_ring_p->descs_pending - TX_FULL_MARK));
   1091 	}
   1092 
   1093 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1094 	    "<== nxge_txdma_reclaim status = 0x%08x", status));
   1095 
   1096 	return (status);
   1097 }
   1098 
   1099 /*
   1100  * nxge_tx_intr
   1101  *
   1102  *	Process a TDC interrupt
   1103  *
   1104  * Arguments:
   1105  * 	arg1	A Logical Device state Vector (LSV) data structure.
   1106  * 	arg2	nxge_t *
   1107  *
   1108  * Notes:
   1109  *
   1110  * NPI/NXGE function calls:
   1111  *	npi_txdma_control_status()
   1112  *	npi_intr_ldg_mgmt_set()
   1113  *
   1114  *	nxge_tx_err_evnts()
   1115  *	nxge_txdma_reclaim()
   1116  *
   1117  * Registers accessed:
   1118  *	TX_CS		DMC+0x40028 Transmit Control And Status
   1119  *	PIO_LDSV
   1120  *
   1121  * Context:
   1122  *	Any domain
   1123  */
   1124 uint_t
   1125 nxge_tx_intr(void *arg1, void *arg2)
   1126 {
   1127 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
   1128 	p_nxge_t		nxgep = (p_nxge_t)arg2;
   1129 	p_nxge_ldg_t		ldgp;
   1130 	uint8_t			channel;
   1131 	uint32_t		vindex;
   1132 	npi_handle_t		handle;
   1133 	tx_cs_t			cs;
   1134 	p_tx_ring_t 		*tx_rings;
   1135 	p_tx_ring_t 		tx_ring_p;
   1136 	npi_status_t		rs = NPI_SUCCESS;
   1137 	uint_t 			serviced = DDI_INTR_UNCLAIMED;
   1138 	nxge_status_t 		status = NXGE_OK;
   1139 
   1140 	if (ldvp == NULL) {
   1141 		NXGE_DEBUG_MSG((NULL, INT_CTL,
   1142 		    "<== nxge_tx_intr: nxgep $%p ldvp $%p",
   1143 		    nxgep, ldvp));
   1144 		return (DDI_INTR_UNCLAIMED);
   1145 	}
   1146 
   1147 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
   1148 		nxgep = ldvp->nxgep;
   1149 	}
   1150 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
   1151 	    "==> nxge_tx_intr: nxgep(arg2) $%p ldvp(arg1) $%p",
   1152 	    nxgep, ldvp));
   1153 
   1154 	if ((!(nxgep->drv_state & STATE_HW_INITIALIZED)) ||
   1155 	    (nxgep->nxge_mac_state != NXGE_MAC_STARTED)) {
   1156 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
   1157 		    "<== nxge_tx_intr: interface not started or intialized"));
   1158 		return (DDI_INTR_CLAIMED);
   1159 	}
   1160 
   1161 	/*
   1162 	 * This interrupt handler is for a specific
   1163 	 * transmit dma channel.
   1164 	 */
   1165 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   1166 	/* Get the control and status for this channel. */
   1167 	channel = ldvp->channel;
   1168 	ldgp = ldvp->ldgp;
   1169 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
   1170 	    "==> nxge_tx_intr: nxgep $%p ldvp (ldvp) $%p "
   1171 	    "channel %d",
   1172 	    nxgep, ldvp, channel));
   1173 
   1174 	rs = npi_txdma_control_status(handle, OP_GET, channel, &cs);
   1175 	vindex = ldvp->vdma_index;
   1176 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
   1177 	    "==> nxge_tx_intr:channel %d ring index %d status 0x%08x",
   1178 	    channel, vindex, rs));
   1179 	if (!rs && cs.bits.ldw.mk) {
   1180 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
   1181 		    "==> nxge_tx_intr:channel %d ring index %d "
   1182 		    "status 0x%08x (mk bit set)",
   1183 		    channel, vindex, rs));
   1184 		tx_rings = nxgep->tx_rings->rings;
   1185 		tx_ring_p = tx_rings[vindex];
   1186 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
   1187 		    "==> nxge_tx_intr:channel %d ring index %d "
   1188 		    "status 0x%08x (mk bit set, calling reclaim)",
   1189 		    channel, vindex, rs));
   1190 
   1191 		nxge_tx_ring_task((void *)tx_ring_p);
   1192 	}
   1193 
   1194 	/*
   1195 	 * Process other transmit control and status.
   1196 	 * Check the ldv state.
   1197 	 */
   1198 	status = nxge_tx_err_evnts(nxgep, ldvp->vdma_index, ldvp, cs);
   1199 	/*
   1200 	 * Rearm this logical group if this is a single device
   1201 	 * group.
   1202 	 */
   1203 	if (ldgp->nldvs == 1) {
   1204 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
   1205 		    "==> nxge_tx_intr: rearm"));
   1206 		if (status == NXGE_OK) {
   1207 			if (isLDOMguest(nxgep)) {
   1208 				nxge_hio_ldgimgn(nxgep, ldgp);
   1209 			} else {
   1210 				(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
   1211 				    B_TRUE, ldgp->ldg_timer);
   1212 			}
   1213 		}
   1214 	}
   1215 
   1216 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_tx_intr"));
   1217 	serviced = DDI_INTR_CLAIMED;
   1218 	return (serviced);
   1219 }
   1220 
   1221 void
   1222 nxge_txdma_stop(p_nxge_t nxgep)	/* Dead */
   1223 {
   1224 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop"));
   1225 
   1226 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
   1227 
   1228 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop"));
   1229 }
   1230 
   1231 void
   1232 nxge_txdma_stop_start(p_nxge_t nxgep) /* Dead */
   1233 {
   1234 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop_start"));
   1235 
   1236 	(void) nxge_txdma_stop(nxgep);
   1237 
   1238 	(void) nxge_fixup_txdma_rings(nxgep);
   1239 	(void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START);
   1240 	(void) nxge_tx_mac_enable(nxgep);
   1241 	(void) nxge_txdma_hw_kick(nxgep);
   1242 
   1243 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop_start"));
   1244 }
   1245 
   1246 npi_status_t
   1247 nxge_txdma_channel_disable(
   1248 	nxge_t *nxge,
   1249 	int channel)
   1250 {
   1251 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxge);
   1252 	npi_status_t	rs;
   1253 	tdmc_intr_dbg_t	intr_dbg;
   1254 
   1255 	/*
   1256 	 * Stop the dma channel and wait for the stop-done.
   1257 	 * If the stop-done bit is not present, then force
   1258 	 * an error so TXC will stop.
   1259 	 * All channels bound to this port need to be stopped
   1260 	 * and reset after injecting an interrupt error.
   1261 	 */
   1262 	rs = npi_txdma_channel_disable(handle, channel);
   1263 	NXGE_DEBUG_MSG((nxge, MEM3_CTL,
   1264 	    "==> nxge_txdma_channel_disable(%d) "
   1265 	    "rs 0x%x", channel, rs));
   1266 	if (rs != NPI_SUCCESS) {
   1267 		/* Inject any error */
   1268 		intr_dbg.value = 0;
   1269 		intr_dbg.bits.ldw.nack_pref = 1;
   1270 		NXGE_DEBUG_MSG((nxge, MEM3_CTL,
   1271 		    "==> nxge_txdma_hw_mode: "
   1272 		    "channel %d (stop failed 0x%x) "
   1273 		    "(inject err)", rs, channel));
   1274 		(void) npi_txdma_inj_int_error_set(
   1275 		    handle, channel, &intr_dbg);
   1276 		rs = npi_txdma_channel_disable(handle, channel);
   1277 		NXGE_DEBUG_MSG((nxge, MEM3_CTL,
   1278 		    "==> nxge_txdma_hw_mode: "
   1279 		    "channel %d (stop again 0x%x) "
   1280 		    "(after inject err)",
   1281 		    rs, channel));
   1282 	}
   1283 
   1284 	return (rs);
   1285 }
   1286 
   1287 /*
   1288  * nxge_txdma_hw_mode
   1289  *
   1290  *	Toggle all TDCs on (enable) or off (disable).
   1291  *
   1292  * Arguments:
   1293  * 	nxgep
   1294  * 	enable	Enable or disable a TDC.
   1295  *
   1296  * Notes:
   1297  *
   1298  * NPI/NXGE function calls:
   1299  *	npi_txdma_channel_enable(TX_CS)
   1300  *	npi_txdma_channel_disable(TX_CS)
   1301  *	npi_txdma_inj_int_error_set(TDMC_INTR_DBG)
   1302  *
   1303  * Registers accessed:
   1304  *	TX_CS		DMC+0x40028 Transmit Control And Status
   1305  *	TDMC_INTR_DBG	DMC + 0x40060 Transmit DMA Interrupt Debug
   1306  *
   1307  * Context:
   1308  *	Any domain
   1309  */
   1310 nxge_status_t
   1311 nxge_txdma_hw_mode(p_nxge_t nxgep, boolean_t enable)
   1312 {
   1313 	nxge_grp_set_t *set = &nxgep->tx_set;
   1314 
   1315 	npi_handle_t	handle;
   1316 	nxge_status_t	status;
   1317 	npi_status_t	rs;
   1318 	int		tdc;
   1319 
   1320 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   1321 	    "==> nxge_txdma_hw_mode: enable mode %d", enable));
   1322 
   1323 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
   1324 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1325 		    "<== nxge_txdma_mode: not initialized"));
   1326 		return (NXGE_ERROR);
   1327 	}
   1328 
   1329 	if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) {
   1330 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1331 		    "<== nxge_txdma_hw_mode: NULL ring pointer(s)"));
   1332 		return (NXGE_ERROR);
   1333 	}
   1334 
   1335 	/* Enable or disable all of the TDCs owned by us. */
   1336 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   1337 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   1338 		if ((1 << tdc) & set->owned.map) {
   1339 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   1340 			if (ring) {
   1341 				NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   1342 				    "==> nxge_txdma_hw_mode: channel %d", tdc));
   1343 				if (enable) {
   1344 					rs = npi_txdma_channel_enable
   1345 					    (handle, tdc);
   1346 					NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   1347 					    "==> nxge_txdma_hw_mode: "
   1348 					    "channel %d (enable) rs 0x%x",
   1349 					    tdc, rs));
   1350 				} else {
   1351 					rs = nxge_txdma_channel_disable
   1352 					    (nxgep, tdc);
   1353 				}
   1354 			}
   1355 		}
   1356 	}
   1357 
   1358 	status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs);
   1359 
   1360 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   1361 	    "<== nxge_txdma_hw_mode: status 0x%x", status));
   1362 
   1363 	return (status);
   1364 }
   1365 
   1366 void
   1367 nxge_txdma_enable_channel(p_nxge_t nxgep, uint16_t channel)
   1368 {
   1369 	npi_handle_t		handle;
   1370 
   1371 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
   1372 	    "==> nxge_txdma_enable_channel: channel %d", channel));
   1373 
   1374 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   1375 	/* enable the transmit dma channels */
   1376 	(void) npi_txdma_channel_enable(handle, channel);
   1377 
   1378 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_txdma_enable_channel"));
   1379 }
   1380 
   1381 void
   1382 nxge_txdma_disable_channel(p_nxge_t nxgep, uint16_t channel)
   1383 {
   1384 	npi_handle_t		handle;
   1385 
   1386 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
   1387 	    "==> nxge_txdma_disable_channel: channel %d", channel));
   1388 
   1389 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   1390 	/* stop the transmit dma channels */
   1391 	(void) npi_txdma_channel_disable(handle, channel);
   1392 
   1393 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_disable_channel"));
   1394 }
   1395 
   1396 /*
   1397  * nxge_txdma_stop_inj_err
   1398  *
   1399  *	Stop a TDC.  If at first we don't succeed, inject an error.
   1400  *
   1401  * Arguments:
   1402  * 	nxgep
   1403  * 	channel		The channel to stop.
   1404  *
   1405  * Notes:
   1406  *
   1407  * NPI/NXGE function calls:
   1408  *	npi_txdma_channel_disable()
   1409  *	npi_txdma_inj_int_error_set()
   1410  * #if defined(NXGE_DEBUG)
   1411  *	nxge_txdma_regs_dump_channels(nxgep);
   1412  * #endif
   1413  *
   1414  * Registers accessed:
   1415  *	TX_CS		DMC+0x40028 Transmit Control And Status
   1416  *	TDMC_INTR_DBG	DMC + 0x40060 Transmit DMA Interrupt Debug
   1417  *
   1418  * Context:
   1419  *	Any domain
   1420  */
   1421 int
   1422 nxge_txdma_stop_inj_err(p_nxge_t nxgep, int channel)
   1423 {
   1424 	npi_handle_t		handle;
   1425 	tdmc_intr_dbg_t		intr_dbg;
   1426 	int			status;
   1427 	npi_status_t		rs = NPI_SUCCESS;
   1428 
   1429 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop_inj_err"));
   1430 	/*
   1431 	 * Stop the dma channel waits for the stop done.
   1432 	 * If the stop done bit is not set, then create
   1433 	 * an error.
   1434 	 */
   1435 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   1436 	rs = npi_txdma_channel_disable(handle, channel);
   1437 	status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs);
   1438 	if (status == NXGE_OK) {
   1439 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1440 		    "<== nxge_txdma_stop_inj_err (channel %d): "
   1441 		    "stopped OK", channel));
   1442 		return (status);
   1443 	}
   1444 
   1445 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   1446 	    "==> nxge_txdma_stop_inj_err (channel %d): stop failed (0x%x) "
   1447 	    "injecting error", channel, rs));
   1448 	/* Inject any error */
   1449 	intr_dbg.value = 0;
   1450 	intr_dbg.bits.ldw.nack_pref = 1;
   1451 	(void) npi_txdma_inj_int_error_set(handle, channel, &intr_dbg);
   1452 
   1453 	/* Stop done bit will be set as a result of error injection */
   1454 	rs = npi_txdma_channel_disable(handle, channel);
   1455 	status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs);
   1456 	if (!(rs & NPI_TXDMA_STOP_FAILED)) {
   1457 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1458 		    "<== nxge_txdma_stop_inj_err (channel %d): "
   1459 		    "stopped OK ", channel));
   1460 		return (status);
   1461 	}
   1462 
   1463 #if	defined(NXGE_DEBUG)
   1464 	nxge_txdma_regs_dump_channels(nxgep);
   1465 #endif
   1466 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   1467 	    "==> nxge_txdma_stop_inj_err (channel): stop failed (0x%x) "
   1468 	    " (injected error but still not stopped)", channel, rs));
   1469 
   1470 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop_inj_err"));
   1471 	return (status);
   1472 }
   1473 
   1474 /*ARGSUSED*/
   1475 void
   1476 nxge_fixup_txdma_rings(p_nxge_t nxgep)
   1477 {
   1478 	nxge_grp_set_t *set = &nxgep->tx_set;
   1479 	int tdc;
   1480 
   1481 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_txdma_rings"));
   1482 
   1483 	if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) {
   1484 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1485 		    "<== nxge_fixup_txdma_rings: NULL ring pointer(s)"));
   1486 		return;
   1487 	}
   1488 
   1489 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   1490 		if ((1 << tdc) & set->owned.map) {
   1491 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   1492 			if (ring) {
   1493 				NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   1494 				    "==> nxge_fixup_txdma_rings: channel %d",
   1495 				    tdc));
   1496 				nxge_txdma_fixup_channel(nxgep, ring, tdc);
   1497 			}
   1498 		}
   1499 	}
   1500 
   1501 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_fixup_txdma_rings"));
   1502 }
   1503 
   1504 /*ARGSUSED*/
   1505 void
   1506 nxge_txdma_fix_channel(p_nxge_t nxgep, uint16_t channel)
   1507 {
   1508 	p_tx_ring_t	ring_p;
   1509 
   1510 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fix_channel"));
   1511 	ring_p = nxge_txdma_get_ring(nxgep, channel);
   1512 	if (ring_p == NULL) {
   1513 		NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_channel"));
   1514 		return;
   1515 	}
   1516 
   1517 	if (ring_p->tdc != channel) {
   1518 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1519 		    "<== nxge_txdma_fix_channel: channel not matched "
   1520 		    "ring tdc %d passed channel",
   1521 		    ring_p->tdc, channel));
   1522 		return;
   1523 	}
   1524 
   1525 	nxge_txdma_fixup_channel(nxgep, ring_p, channel);
   1526 
   1527 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_channel"));
   1528 }
   1529 
   1530 /*ARGSUSED*/
   1531 void
   1532 nxge_txdma_fixup_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, uint16_t channel)
   1533 {
   1534 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fixup_channel"));
   1535 
   1536 	if (ring_p == NULL) {
   1537 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1538 		    "<== nxge_txdma_fixup_channel: NULL ring pointer"));
   1539 		return;
   1540 	}
   1541 
   1542 	if (ring_p->tdc != channel) {
   1543 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1544 		    "<== nxge_txdma_fixup_channel: channel not matched "
   1545 		    "ring tdc %d passed channel",
   1546 		    ring_p->tdc, channel));
   1547 		return;
   1548 	}
   1549 
   1550 	MUTEX_ENTER(&ring_p->lock);
   1551 	(void) nxge_txdma_reclaim(nxgep, ring_p, 0);
   1552 	ring_p->rd_index = 0;
   1553 	ring_p->wr_index = 0;
   1554 	ring_p->ring_head.value = 0;
   1555 	ring_p->ring_kick_tail.value = 0;
   1556 	ring_p->descs_pending = 0;
   1557 	MUTEX_EXIT(&ring_p->lock);
   1558 
   1559 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fixup_channel"));
   1560 }
   1561 
   1562 /*ARGSUSED*/
   1563 void
   1564 nxge_txdma_hw_kick(p_nxge_t nxgep)
   1565 {
   1566 	nxge_grp_set_t *set = &nxgep->tx_set;
   1567 	int tdc;
   1568 
   1569 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hw_kick"));
   1570 
   1571 	if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) {
   1572 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1573 		    "<== nxge_txdma_hw_kick: NULL ring pointer(s)"));
   1574 		return;
   1575 	}
   1576 
   1577 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   1578 		if ((1 << tdc) & set->owned.map) {
   1579 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   1580 			if (ring) {
   1581 				NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   1582 				    "==> nxge_txdma_hw_kick: channel %d", tdc));
   1583 				nxge_txdma_hw_kick_channel(nxgep, ring, tdc);
   1584 			}
   1585 		}
   1586 	}
   1587 
   1588 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hw_kick"));
   1589 }
   1590 
   1591 /*ARGSUSED*/
   1592 void
   1593 nxge_txdma_kick_channel(p_nxge_t nxgep, uint16_t channel)
   1594 {
   1595 	p_tx_ring_t	ring_p;
   1596 
   1597 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_kick_channel"));
   1598 
   1599 	ring_p = nxge_txdma_get_ring(nxgep, channel);
   1600 	if (ring_p == NULL) {
   1601 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1602 		    " nxge_txdma_kick_channel"));
   1603 		return;
   1604 	}
   1605 
   1606 	if (ring_p->tdc != channel) {
   1607 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1608 		    "<== nxge_txdma_kick_channel: channel not matched "
   1609 		    "ring tdc %d passed channel",
   1610 		    ring_p->tdc, channel));
   1611 		return;
   1612 	}
   1613 
   1614 	nxge_txdma_hw_kick_channel(nxgep, ring_p, channel);
   1615 
   1616 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_kick_channel"));
   1617 }
   1618 
   1619 /*ARGSUSED*/
   1620 void
   1621 nxge_txdma_hw_kick_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, uint16_t channel)
   1622 {
   1623 
   1624 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hw_kick_channel"));
   1625 
   1626 	if (ring_p == NULL) {
   1627 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1628 		    "<== nxge_txdma_hw_kick_channel: NULL ring pointer"));
   1629 		return;
   1630 	}
   1631 
   1632 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hw_kick_channel"));
   1633 }
   1634 
   1635 /*
   1636  * nxge_check_tx_hang
   1637  *
   1638  *	Check the state of all TDCs belonging to nxgep.
   1639  *
   1640  * Arguments:
   1641  * 	nxgep
   1642  *
   1643  * Notes:
   1644  *	Called by nxge_hw.c:nxge_check_hw_state().
   1645  *
   1646  * NPI/NXGE function calls:
   1647  *
   1648  * Registers accessed:
   1649  *
   1650  * Context:
   1651  *	Any domain
   1652  */
   1653 /*ARGSUSED*/
   1654 void
   1655 nxge_check_tx_hang(p_nxge_t nxgep)
   1656 {
   1657 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_check_tx_hang"));
   1658 
   1659 	if ((!(nxgep->drv_state & STATE_HW_INITIALIZED)) ||
   1660 	    (nxgep->nxge_mac_state != NXGE_MAC_STARTED)) {
   1661 		goto nxge_check_tx_hang_exit;
   1662 	}
   1663 
   1664 	/*
   1665 	 * Needs inputs from hardware for regs:
   1666 	 *	head index had not moved since last timeout.
   1667 	 *	packets not transmitted or stuffed registers.
   1668 	 */
   1669 	if (nxge_txdma_hung(nxgep)) {
   1670 		nxge_fixup_hung_txdma_rings(nxgep);
   1671 	}
   1672 
   1673 nxge_check_tx_hang_exit:
   1674 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_check_tx_hang"));
   1675 }
   1676 
   1677 /*
   1678  * nxge_txdma_hung
   1679  *
   1680  *	Reset a TDC.
   1681  *
   1682  * Arguments:
   1683  * 	nxgep
   1684  * 	channel		The channel to reset.
   1685  * 	reg_data	The current TX_CS.
   1686  *
   1687  * Notes:
   1688  *	Called by nxge_check_tx_hang()
   1689  *
   1690  * NPI/NXGE function calls:
   1691  *	nxge_txdma_channel_hung()
   1692  *
   1693  * Registers accessed:
   1694  *
   1695  * Context:
   1696  *	Any domain
   1697  */
   1698 int
   1699 nxge_txdma_hung(p_nxge_t nxgep)
   1700 {
   1701 	nxge_grp_set_t	*set = &nxgep->tx_set;
   1702 	int		tdc;
   1703 	boolean_t	shared;
   1704 
   1705 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hung"));
   1706 
   1707 	if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) {
   1708 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1709 		    "<== nxge_txdma_hung: NULL ring pointer(s)"));
   1710 		return (B_FALSE);
   1711 	}
   1712 
   1713 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   1714 		/*
   1715 		 * Grab the shared state of the TDC.
   1716 		 */
   1717 		if (isLDOMservice(nxgep)) {
   1718 			nxge_hio_data_t *nhd =
   1719 			    (nxge_hio_data_t *)nxgep->nxge_hw_p->hio;
   1720 
   1721 			MUTEX_ENTER(&nhd->lock);
   1722 			shared = nxgep->tdc_is_shared[tdc];
   1723 			MUTEX_EXIT(&nhd->lock);
   1724 		} else {
   1725 			shared = B_FALSE;
   1726 		}
   1727 
   1728 		/*
   1729 		 * Now, process continue to process.
   1730 		 */
   1731 		if (((1 << tdc) & set->owned.map) && !shared) {
   1732 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   1733 			if (ring) {
   1734 				if (nxge_txdma_channel_hung(nxgep, ring, tdc)) {
   1735 					NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1736 					    "==> nxge_txdma_hung: TDC %d hung",
   1737 					    tdc));
   1738 					return (B_TRUE);
   1739 				}
   1740 			}
   1741 		}
   1742 	}
   1743 
   1744 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hung"));
   1745 
   1746 	return (B_FALSE);
   1747 }
   1748 
   1749 /*
   1750  * nxge_txdma_channel_hung
   1751  *
   1752  *	Reset a TDC.
   1753  *
   1754  * Arguments:
   1755  * 	nxgep
   1756  * 	ring		<channel>'s ring.
   1757  * 	channel		The channel to reset.
   1758  *
   1759  * Notes:
   1760  *	Called by nxge_txdma.c:nxge_txdma_hung()
   1761  *
   1762  * NPI/NXGE function calls:
   1763  *	npi_txdma_ring_head_get()
   1764  *
   1765  * Registers accessed:
   1766  *	TX_RING_HDL	DMC+0x40010 Transmit Ring Head Low
   1767  *
   1768  * Context:
   1769  *	Any domain
   1770  */
   1771 int
   1772 nxge_txdma_channel_hung(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, uint16_t channel)
   1773 {
   1774 	uint16_t		head_index, tail_index;
   1775 	boolean_t		head_wrap, tail_wrap;
   1776 	npi_handle_t		handle;
   1777 	tx_ring_hdl_t		tx_head;
   1778 	uint_t			tx_rd_index;
   1779 
   1780 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_channel_hung"));
   1781 
   1782 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   1783 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1784 	    "==> nxge_txdma_channel_hung: channel %d", channel));
   1785 	MUTEX_ENTER(&tx_ring_p->lock);
   1786 	(void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0);
   1787 
   1788 	tail_index = tx_ring_p->wr_index;
   1789 	tail_wrap = tx_ring_p->wr_index_wrap;
   1790 	tx_rd_index = tx_ring_p->rd_index;
   1791 	MUTEX_EXIT(&tx_ring_p->lock);
   1792 
   1793 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1794 	    "==> nxge_txdma_channel_hung: tdc %d tx_rd_index %d "
   1795 	    "tail_index %d tail_wrap %d ",
   1796 	    channel, tx_rd_index, tail_index, tail_wrap));
   1797 	/*
   1798 	 * Read the hardware maintained transmit head
   1799 	 * and wrap around bit.
   1800 	 */
   1801 	(void) npi_txdma_ring_head_get(handle, channel, &tx_head);
   1802 	head_index =  tx_head.bits.ldw.head;
   1803 	head_wrap = tx_head.bits.ldw.wrap;
   1804 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1805 	    "==> nxge_txdma_channel_hung: "
   1806 	    "tx_rd_index %d tail %d tail_wrap %d "
   1807 	    "head %d wrap %d",
   1808 	    tx_rd_index, tail_index, tail_wrap,
   1809 	    head_index, head_wrap));
   1810 
   1811 	if (TXDMA_RING_EMPTY(head_index, head_wrap,
   1812 	    tail_index, tail_wrap) &&
   1813 	    (head_index == tx_rd_index)) {
   1814 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1815 		    "==> nxge_txdma_channel_hung: EMPTY"));
   1816 		return (B_FALSE);
   1817 	}
   1818 
   1819 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1820 	    "==> nxge_txdma_channel_hung: Checking if ring full"));
   1821 	if (TXDMA_RING_FULL(head_index, head_wrap, tail_index,
   1822 	    tail_wrap)) {
   1823 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1824 		    "==> nxge_txdma_channel_hung: full"));
   1825 		return (B_TRUE);
   1826 	}
   1827 
   1828 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_channel_hung"));
   1829 
   1830 	return (B_FALSE);
   1831 }
   1832 
   1833 /*
   1834  * nxge_fixup_hung_txdma_rings
   1835  *
   1836  *	Disable a TDC.
   1837  *
   1838  * Arguments:
   1839  * 	nxgep
   1840  * 	channel		The channel to reset.
   1841  * 	reg_data	The current TX_CS.
   1842  *
   1843  * Notes:
   1844  *	Called by nxge_check_tx_hang()
   1845  *
   1846  * NPI/NXGE function calls:
   1847  *	npi_txdma_ring_head_get()
   1848  *
   1849  * Registers accessed:
   1850  *	TX_RING_HDL	DMC+0x40010 Transmit Ring Head Low
   1851  *
   1852  * Context:
   1853  *	Any domain
   1854  */
   1855 /*ARGSUSED*/
   1856 void
   1857 nxge_fixup_hung_txdma_rings(p_nxge_t nxgep)
   1858 {
   1859 	nxge_grp_set_t *set = &nxgep->tx_set;
   1860 	int tdc;
   1861 
   1862 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_hung_txdma_rings"));
   1863 
   1864 	if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) {
   1865 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1866 		    "<== nxge_fixup_hung_txdma_rings: NULL ring pointer(s)"));
   1867 		return;
   1868 	}
   1869 
   1870 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   1871 		if ((1 << tdc) & set->owned.map) {
   1872 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   1873 			if (ring) {
   1874 				nxge_txdma_fixup_hung_channel(nxgep, ring, tdc);
   1875 				NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1876 				    "==> nxge_fixup_hung_txdma_rings: TDC %d",
   1877 				    tdc));
   1878 			}
   1879 		}
   1880 	}
   1881 
   1882 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_fixup_hung_txdma_rings"));
   1883 }
   1884 
   1885 /*
   1886  * nxge_txdma_fixup_hung_channel
   1887  *
   1888  *	'Fix' a hung TDC.
   1889  *
   1890  * Arguments:
   1891  * 	nxgep
   1892  * 	channel		The channel to fix.
   1893  *
   1894  * Notes:
   1895  *	Called by nxge_fixup_hung_txdma_rings()
   1896  *
   1897  *	1. Reclaim the TDC.
   1898  *	2. Disable the TDC.
   1899  *
   1900  * NPI/NXGE function calls:
   1901  *	nxge_txdma_reclaim()
   1902  *	npi_txdma_channel_disable(TX_CS)
   1903  *	npi_txdma_inj_int_error_set(TDMC_INTR_DBG)
   1904  *
   1905  * Registers accessed:
   1906  *	TX_CS		DMC+0x40028 Transmit Control And Status
   1907  *	TDMC_INTR_DBG	DMC + 0x40060 Transmit DMA Interrupt Debug
   1908  *
   1909  * Context:
   1910  *	Any domain
   1911  */
   1912 /*ARGSUSED*/
   1913 void
   1914 nxge_txdma_fix_hung_channel(p_nxge_t nxgep, uint16_t channel)
   1915 {
   1916 	p_tx_ring_t	ring_p;
   1917 
   1918 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fix_hung_channel"));
   1919 	ring_p = nxge_txdma_get_ring(nxgep, channel);
   1920 	if (ring_p == NULL) {
   1921 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1922 		    "<== nxge_txdma_fix_hung_channel"));
   1923 		return;
   1924 	}
   1925 
   1926 	if (ring_p->tdc != channel) {
   1927 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1928 		    "<== nxge_txdma_fix_hung_channel: channel not matched "
   1929 		    "ring tdc %d passed channel",
   1930 		    ring_p->tdc, channel));
   1931 		return;
   1932 	}
   1933 
   1934 	nxge_txdma_fixup_channel(nxgep, ring_p, channel);
   1935 
   1936 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_hung_channel"));
   1937 }
   1938 
   1939 /*ARGSUSED*/
   1940 void
   1941 nxge_txdma_fixup_hung_channel(p_nxge_t nxgep, p_tx_ring_t ring_p,
   1942 	uint16_t channel)
   1943 {
   1944 	npi_handle_t		handle;
   1945 	tdmc_intr_dbg_t		intr_dbg;
   1946 	int			status = NXGE_OK;
   1947 
   1948 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fixup_hung_channel"));
   1949 
   1950 	if (ring_p == NULL) {
   1951 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1952 		    "<== nxge_txdma_fixup_channel: NULL ring pointer"));
   1953 		return;
   1954 	}
   1955 
   1956 	if (ring_p->tdc != channel) {
   1957 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1958 		    "<== nxge_txdma_fixup_hung_channel: channel "
   1959 		    "not matched "
   1960 		    "ring tdc %d passed channel",
   1961 		    ring_p->tdc, channel));
   1962 		return;
   1963 	}
   1964 
   1965 	/* Reclaim descriptors */
   1966 	MUTEX_ENTER(&ring_p->lock);
   1967 	(void) nxge_txdma_reclaim(nxgep, ring_p, 0);
   1968 	MUTEX_EXIT(&ring_p->lock);
   1969 
   1970 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   1971 	/*
   1972 	 * Stop the dma channel waits for the stop done.
   1973 	 * If the stop done bit is not set, then force
   1974 	 * an error.
   1975 	 */
   1976 	status = npi_txdma_channel_disable(handle, channel);
   1977 	if (!(status & NPI_TXDMA_STOP_FAILED)) {
   1978 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1979 		    "<== nxge_txdma_fixup_hung_channel: stopped OK "
   1980 		    "ring tdc %d passed channel %d",
   1981 		    ring_p->tdc, channel));
   1982 		return;
   1983 	}
   1984 
   1985 	/* Inject any error */
   1986 	intr_dbg.value = 0;
   1987 	intr_dbg.bits.ldw.nack_pref = 1;
   1988 	(void) npi_txdma_inj_int_error_set(handle, channel, &intr_dbg);
   1989 
   1990 	/* Stop done bit will be set as a result of error injection */
   1991 	status = npi_txdma_channel_disable(handle, channel);
   1992 	if (!(status & NPI_TXDMA_STOP_FAILED)) {
   1993 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   1994 		    "<== nxge_txdma_fixup_hung_channel: stopped again"
   1995 		    "ring tdc %d passed channel",
   1996 		    ring_p->tdc, channel));
   1997 		return;
   1998 	}
   1999 
   2000 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
   2001 	    "<== nxge_txdma_fixup_hung_channel: stop done still not set!! "
   2002 	    "ring tdc %d passed channel",
   2003 	    ring_p->tdc, channel));
   2004 
   2005 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fixup_hung_channel"));
   2006 }
   2007 
   2008 /*ARGSUSED*/
   2009 void
   2010 nxge_reclaim_rings(p_nxge_t nxgep)
   2011 {
   2012 	nxge_grp_set_t *set = &nxgep->tx_set;
   2013 	int tdc;
   2014 
   2015 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_reclaim_rings"));
   2016 
   2017 	if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) {
   2018 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   2019 		    "<== nxge_fixup_hung_txdma_rings: NULL ring pointer(s)"));
   2020 		return;
   2021 	}
   2022 
   2023 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   2024 		if ((1 << tdc) & set->owned.map) {
   2025 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   2026 			if (ring) {
   2027 				NXGE_DEBUG_MSG((nxgep, TX_CTL,
   2028 				    "==> nxge_reclaim_rings: TDC %d", tdc));
   2029 				MUTEX_ENTER(&ring->lock);
   2030 				(void) nxge_txdma_reclaim(nxgep, ring, 0);
   2031 				MUTEX_EXIT(&ring->lock);
   2032 			}
   2033 		}
   2034 	}
   2035 
   2036 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_reclaim_rings"));
   2037 }
   2038 
   2039 void
   2040 nxge_txdma_regs_dump_channels(p_nxge_t nxgep)
   2041 {
   2042 	nxge_grp_set_t *set = &nxgep->tx_set;
   2043 	npi_handle_t handle;
   2044 	int tdc;
   2045 
   2046 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_regs_dump_channels"));
   2047 
   2048 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   2049 
   2050 	if (!isLDOMguest(nxgep)) {
   2051 		(void) npi_txdma_dump_fzc_regs(handle);
   2052 
   2053 		/* Dump TXC registers. */
   2054 		(void) npi_txc_dump_fzc_regs(handle);
   2055 		(void) npi_txc_dump_port_fzc_regs(handle, nxgep->function_num);
   2056 	}
   2057 
   2058 	if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) {
   2059 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   2060 		    "<== nxge_fixup_hung_txdma_rings: NULL ring pointer(s)"));
   2061 		return;
   2062 	}
   2063 
   2064 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   2065 		if ((1 << tdc) & set->owned.map) {
   2066 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   2067 			if (ring) {
   2068 				NXGE_DEBUG_MSG((nxgep, TX_CTL,
   2069 				    "==> nxge_txdma_regs_dump_channels: "
   2070 				    "TDC %d", tdc));
   2071 				(void) npi_txdma_dump_tdc_regs(handle, tdc);
   2072 
   2073 				/* Dump TXC registers, if able to. */
   2074 				if (!isLDOMguest(nxgep)) {
   2075 					NXGE_DEBUG_MSG((nxgep, TX_CTL,
   2076 					    "==> nxge_txdma_regs_dump_channels:"
   2077 					    " FZC TDC %d", tdc));
   2078 					(void) npi_txc_dump_tdc_fzc_regs
   2079 					    (handle, tdc);
   2080 				}
   2081 				nxge_txdma_regs_dump(nxgep, tdc);
   2082 			}
   2083 		}
   2084 	}
   2085 
   2086 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_regs_dump"));
   2087 }
   2088 
   2089 void
   2090 nxge_txdma_regs_dump(p_nxge_t nxgep, int channel)
   2091 {
   2092 	npi_handle_t		handle;
   2093 	tx_ring_hdl_t 		hdl;
   2094 	tx_ring_kick_t 		kick;
   2095 	tx_cs_t 		cs;
   2096 	txc_control_t		control;
   2097 	uint32_t		bitmap = 0;
   2098 	uint32_t		burst = 0;
   2099 	uint32_t		bytes = 0;
   2100 	dma_log_page_t		cfg;
   2101 
   2102 	printf("\n\tfunc # %d tdc %d ",
   2103 	    nxgep->function_num, channel);
   2104 	cfg.page_num = 0;
   2105 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   2106 	(void) npi_txdma_log_page_get(handle, channel, &cfg);
   2107 	printf("\n\tlog page func %d valid page 0 %d",
   2108 	    cfg.func_num, cfg.valid);
   2109 	cfg.page_num = 1;
   2110 	(void) npi_txdma_log_page_get(handle, channel, &cfg);
   2111 	printf("\n\tlog page func %d valid page 1 %d",
   2112 	    cfg.func_num, cfg.valid);
   2113 
   2114 	(void) npi_txdma_ring_head_get(handle, channel, &hdl);
   2115 	(void) npi_txdma_desc_kick_reg_get(handle, channel, &kick);
   2116 	printf("\n\thead value is 0x%0llx",
   2117 	    (long long)hdl.value);
   2118 	printf("\n\thead index %d", hdl.bits.ldw.head);
   2119 	printf("\n\tkick value is 0x%0llx",
   2120 	    (long long)kick.value);
   2121 	printf("\n\ttail index %d\n", kick.bits.ldw.tail);
   2122 
   2123 	(void) npi_txdma_control_status(handle, OP_GET, channel, &cs);
   2124 	printf("\n\tControl statue is 0x%0llx", (long long)cs.value);
   2125 	printf("\n\tControl status RST state %d", cs.bits.ldw.rst);
   2126 
   2127 	(void) npi_txc_control(handle, OP_GET, &control);
   2128 	(void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap);
   2129 	(void) npi_txc_dma_max_burst(handle, OP_GET, channel, &burst);
   2130 	(void) npi_txc_dma_bytes_transmitted(handle, channel, &bytes);
   2131 
   2132 	printf("\n\tTXC port control 0x%0llx",
   2133 	    (long long)control.value);
   2134 	printf("\n\tTXC port bitmap 0x%x", bitmap);
   2135 	printf("\n\tTXC max burst %d", burst);
   2136 	printf("\n\tTXC bytes xmt %d\n", bytes);
   2137 
   2138 	{
   2139 		ipp_status_t status;
   2140 
   2141 		(void) npi_ipp_get_status(handle, nxgep->function_num, &status);
   2142 #if defined(__i386)
   2143 		printf("\n\tIPP status 0x%llux\n", (uint64_t)status.value);
   2144 #else
   2145 		printf("\n\tIPP status 0x%lux\n", (uint64_t)status.value);
   2146 #endif
   2147 	}
   2148 }
   2149 
   2150 /*
   2151  * nxge_tdc_hvio_setup
   2152  *
   2153  *	I'm not exactly sure what this code does.
   2154  *
   2155  * Arguments:
   2156  * 	nxgep
   2157  * 	channel	The channel to map.
   2158  *
   2159  * Notes:
   2160  *
   2161  * NPI/NXGE function calls:
   2162  *	na
   2163  *
   2164  * Context:
   2165  *	Service domain?
   2166  */
   2167 #if defined(sun4v) && defined(NIU_LP_WORKAROUND)
   2168 static void
   2169 nxge_tdc_hvio_setup(
   2170 	nxge_t *nxgep, int channel)
   2171 {
   2172 	nxge_dma_common_t	*data;
   2173 	nxge_dma_common_t	*control;
   2174 	tx_ring_t 		*ring;
   2175 
   2176 	ring = nxgep->tx_rings->rings[channel];
   2177 	data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel];
   2178 
   2179 	ring->hv_set = B_FALSE;
   2180 
   2181 	ring->hv_tx_buf_base_ioaddr_pp =
   2182 	    (uint64_t)data->orig_ioaddr_pp;
   2183 	ring->hv_tx_buf_ioaddr_size =
   2184 	    (uint64_t)data->orig_alength;
   2185 
   2186 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel: "
   2187 	    "hv data buf base io $%p size 0x%llx (%d) buf base io $%p "
   2188 	    "orig vatopa base io $%p orig_len 0x%llx (%d)",
   2189 	    ring->hv_tx_buf_base_ioaddr_pp,
   2190 	    ring->hv_tx_buf_ioaddr_size, ring->hv_tx_buf_ioaddr_size,
   2191 	    data->ioaddr_pp, data->orig_vatopa,
   2192 	    data->orig_alength, data->orig_alength));
   2193 
   2194 	control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel];
   2195 
   2196 	ring->hv_tx_cntl_base_ioaddr_pp =
   2197 	    (uint64_t)control->orig_ioaddr_pp;
   2198 	ring->hv_tx_cntl_ioaddr_size =
   2199 	    (uint64_t)control->orig_alength;
   2200 
   2201 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel: "
   2202 	    "hv cntl base io $%p orig ioaddr_pp ($%p) "
   2203 	    "orig vatopa ($%p) size 0x%llx (%d 0x%x)",
   2204 	    ring->hv_tx_cntl_base_ioaddr_pp,
   2205 	    control->orig_ioaddr_pp, control->orig_vatopa,
   2206 	    ring->hv_tx_cntl_ioaddr_size,
   2207 	    control->orig_alength, control->orig_alength));
   2208 }
   2209 #endif
   2210 
   2211 static nxge_status_t
   2212 nxge_map_txdma(p_nxge_t nxgep, int channel)
   2213 {
   2214 	nxge_dma_common_t	**pData;
   2215 	nxge_dma_common_t	**pControl;
   2216 	tx_ring_t 		**pRing, *ring;
   2217 	tx_mbox_t		**mailbox;
   2218 	uint32_t		num_chunks;
   2219 
   2220 	nxge_status_t		status = NXGE_OK;
   2221 
   2222 	NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma"));
   2223 
   2224 	if (!nxgep->tx_cntl_pool_p->buf_allocated) {
   2225 		if (nxge_alloc_tx_mem_pool(nxgep) != NXGE_OK) {
   2226 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   2227 			    "<== nxge_map_txdma: buf not allocated"));
   2228 			return (NXGE_ERROR);
   2229 		}
   2230 	}
   2231 
   2232 	if (nxge_alloc_txb(nxgep, channel) != NXGE_OK)
   2233 		return (NXGE_ERROR);
   2234 
   2235 	num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel];
   2236 	pData = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel];
   2237 	pControl = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel];
   2238 	pRing = &nxgep->tx_rings->rings[channel];
   2239 	mailbox = &nxgep->tx_mbox_areas_p->txmbox_areas_p[channel];
   2240 
   2241 	NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: "
   2242 	    "tx_rings $%p tx_desc_rings $%p",
   2243 	    nxgep->tx_rings, nxgep->tx_rings->rings));
   2244 
   2245 	/*
   2246 	 * Map descriptors from the buffer pools for <channel>.
   2247 	 */
   2248 
   2249 	/*
   2250 	 * Set up and prepare buffer blocks, descriptors
   2251 	 * and mailbox.
   2252 	 */
   2253 	status = nxge_map_txdma_channel(nxgep, channel,
   2254 	    pData, pRing, num_chunks, pControl, mailbox);
   2255 	if (status != NXGE_OK) {
   2256 		NXGE_ERROR_MSG((nxgep, MEM3_CTL,
   2257 		    "==> nxge_map_txdma(%d): nxge_map_txdma_channel() "
   2258 		    "returned 0x%x",
   2259 		    nxgep, channel, status));
   2260 		return (status);
   2261 	}
   2262 
   2263 	ring = *pRing;
   2264 
   2265 	ring->index = (uint16_t)channel;
   2266 	ring->tdc_stats = &nxgep->statsp->tdc_stats[channel];
   2267 
   2268 #if defined(sun4v) && defined(NIU_LP_WORKAROUND)
   2269 	if (isLDOMguest(nxgep)) {
   2270 		(void) nxge_tdc_lp_conf(nxgep, channel);
   2271 	} else {
   2272 		nxge_tdc_hvio_setup(nxgep, channel);
   2273 	}
   2274 #endif
   2275 
   2276 	NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: "
   2277 	    "(status 0x%x channel %d)", status, channel));
   2278 
   2279 	return (status);
   2280 }
   2281 
   2282 static nxge_status_t
   2283 nxge_map_txdma_channel(p_nxge_t nxgep, uint16_t channel,
   2284 	p_nxge_dma_common_t *dma_buf_p,
   2285 	p_tx_ring_t *tx_desc_p,
   2286 	uint32_t num_chunks,
   2287 	p_nxge_dma_common_t *dma_cntl_p,
   2288 	p_tx_mbox_t *tx_mbox_p)
   2289 {
   2290 	int	status = NXGE_OK;
   2291 
   2292 	/*
   2293 	 * Set up and prepare buffer blocks, descriptors
   2294 	 * and mailbox.
   2295 	 */
   2296 	NXGE_ERROR_MSG((nxgep, MEM3_CTL,
   2297 	    "==> nxge_map_txdma_channel (channel %d)", channel));
   2298 	/*
   2299 	 * Transmit buffer blocks
   2300 	 */
   2301 	status = nxge_map_txdma_channel_buf_ring(nxgep, channel,
   2302 	    dma_buf_p, tx_desc_p, num_chunks);
   2303 	if (status != NXGE_OK) {
   2304 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   2305 		    "==> nxge_map_txdma_channel (channel %d): "
   2306 		    "map buffer failed 0x%x", channel, status));
   2307 		goto nxge_map_txdma_channel_exit;
   2308 	}
   2309 
   2310 	/*
   2311 	 * Transmit block ring, and mailbox.
   2312 	 */
   2313 	nxge_map_txdma_channel_cfg_ring(nxgep, channel, dma_cntl_p, *tx_desc_p,
   2314 	    tx_mbox_p);
   2315 
   2316 	goto nxge_map_txdma_channel_exit;
   2317 
   2318 nxge_map_txdma_channel_fail1:
   2319 	NXGE_ERROR_MSG((nxgep, MEM3_CTL,
   2320 	    "==> nxge_map_txdma_channel: unmap buf"
   2321 	    "(status 0x%x channel %d)",
   2322 	    status, channel));
   2323 	nxge_unmap_txdma_channel_buf_ring(nxgep, *tx_desc_p);
   2324 
   2325 nxge_map_txdma_channel_exit:
   2326 	NXGE_ERROR_MSG((nxgep, MEM3_CTL,
   2327 	    "<== nxge_map_txdma_channel: "
   2328 	    "(status 0x%x channel %d)",
   2329 	    status, channel));
   2330 
   2331 	return (status);
   2332 }
   2333 
   2334 /*ARGSUSED*/
   2335 static void
   2336 nxge_unmap_txdma_channel(p_nxge_t nxgep, uint16_t channel)
   2337 {
   2338 	tx_ring_t *ring;
   2339 	tx_mbox_t *mailbox;
   2340 
   2341 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2342 	    "==> nxge_unmap_txdma_channel (channel %d)", channel));
   2343 	/*
   2344 	 * unmap tx block ring, and mailbox.
   2345 	 */
   2346 	ring = nxgep->tx_rings->rings[channel];
   2347 	mailbox = nxgep->tx_mbox_areas_p->txmbox_areas_p[channel];
   2348 
   2349 	(void) nxge_unmap_txdma_channel_cfg_ring(nxgep, ring, mailbox);
   2350 
   2351 	/* unmap buffer blocks */
   2352 	(void) nxge_unmap_txdma_channel_buf_ring(nxgep, ring);
   2353 
   2354 	nxge_free_txb(nxgep, channel);
   2355 
   2356 	/*
   2357 	 * Cleanup the reference to the ring now that it does not exist.
   2358 	 */
   2359 	nxgep->tx_rings->rings[channel] = NULL;
   2360 
   2361 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_unmap_txdma_channel"));
   2362 }
   2363 
   2364 /*
   2365  * nxge_map_txdma_channel_cfg_ring
   2366  *
   2367  *	Map a TDC into our kernel space.
   2368  *	This function allocates all of the per-channel data structures.
   2369  *
   2370  * Arguments:
   2371  * 	nxgep
   2372  * 	dma_channel	The channel to map.
   2373  *	dma_cntl_p
   2374  *	tx_ring_p	dma_channel's transmit ring
   2375  *	tx_mbox_p	dma_channel's mailbox
   2376  *
   2377  * Notes:
   2378  *
   2379  * NPI/NXGE function calls:
   2380  *	nxge_setup_dma_common()
   2381  *
   2382  * Registers accessed:
   2383  *	none.
   2384  *
   2385  * Context:
   2386  *	Any domain
   2387  */
   2388 /*ARGSUSED*/
   2389 static void
   2390 nxge_map_txdma_channel_cfg_ring(p_nxge_t nxgep, uint16_t dma_channel,
   2391 	p_nxge_dma_common_t *dma_cntl_p,
   2392 	p_tx_ring_t tx_ring_p,
   2393 	p_tx_mbox_t *tx_mbox_p)
   2394 {
   2395 	p_tx_mbox_t 		mboxp;
   2396 	p_nxge_dma_common_t 	cntl_dmap;
   2397 	p_nxge_dma_common_t 	dmap;
   2398 	p_tx_rng_cfig_t		tx_ring_cfig_p;
   2399 	p_tx_ring_kick_t	tx_ring_kick_p;
   2400 	p_tx_cs_t		tx_cs_p;
   2401 	p_tx_dma_ent_msk_t	tx_evmask_p;
   2402 	p_txdma_mbh_t		mboxh_p;
   2403 	p_txdma_mbl_t		mboxl_p;
   2404 	uint64_t		tx_desc_len;
   2405 
   2406 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2407 	    "==> nxge_map_txdma_channel_cfg_ring"));
   2408 
   2409 	cntl_dmap = *dma_cntl_p;
   2410 
   2411 	dmap = (p_nxge_dma_common_t)&tx_ring_p->tdc_desc;
   2412 	nxge_setup_dma_common(dmap, cntl_dmap, tx_ring_p->tx_ring_size,
   2413 	    sizeof (tx_desc_t));
   2414 	/*
   2415 	 * Zero out transmit ring descriptors.
   2416 	 */
   2417 	bzero((caddr_t)dmap->kaddrp, dmap->alength);
   2418 	tx_ring_cfig_p = &(tx_ring_p->tx_ring_cfig);
   2419 	tx_ring_kick_p = &(tx_ring_p->tx_ring_kick);
   2420 	tx_cs_p = &(tx_ring_p->tx_cs);
   2421 	tx_evmask_p = &(tx_ring_p->tx_evmask);
   2422 	tx_ring_cfig_p->value = 0;
   2423 	tx_ring_kick_p->value = 0;
   2424 	tx_cs_p->value = 0;
   2425 	tx_evmask_p->value = 0;
   2426 
   2427 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2428 	    "==> nxge_map_txdma_channel_cfg_ring: channel %d des $%p",
   2429 	    dma_channel,
   2430 	    dmap->dma_cookie.dmac_laddress));
   2431 
   2432 	tx_ring_cfig_p->value = 0;
   2433 	tx_desc_len = (uint64_t)(tx_ring_p->tx_ring_size >> 3);
   2434 	tx_ring_cfig_p->value =
   2435 	    (dmap->dma_cookie.dmac_laddress & TX_RNG_CFIG_ADDR_MASK) |
   2436 	    (tx_desc_len << TX_RNG_CFIG_LEN_SHIFT);
   2437 
   2438 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2439 	    "==> nxge_map_txdma_channel_cfg_ring: channel %d cfg 0x%llx",
   2440 	    dma_channel,
   2441 	    tx_ring_cfig_p->value));
   2442 
   2443 	tx_cs_p->bits.ldw.rst = 1;
   2444 
   2445 	/* Map in mailbox */
   2446 	mboxp = (p_tx_mbox_t)
   2447 	    KMEM_ZALLOC(sizeof (tx_mbox_t), KM_SLEEP);
   2448 	dmap = (p_nxge_dma_common_t)&mboxp->tx_mbox;
   2449 	nxge_setup_dma_common(dmap, cntl_dmap, 1, sizeof (txdma_mailbox_t));
   2450 	mboxh_p = (p_txdma_mbh_t)&tx_ring_p->tx_mbox_mbh;
   2451 	mboxl_p = (p_txdma_mbl_t)&tx_ring_p->tx_mbox_mbl;
   2452 	mboxh_p->value = mboxl_p->value = 0;
   2453 
   2454 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2455 	    "==> nxge_map_txdma_channel_cfg_ring: mbox 0x%lx",
   2456 	    dmap->dma_cookie.dmac_laddress));
   2457 
   2458 	mboxh_p->bits.ldw.mbaddr = ((dmap->dma_cookie.dmac_laddress >>
   2459 	    TXDMA_MBH_ADDR_SHIFT) & TXDMA_MBH_MASK);
   2460 
   2461 	mboxl_p->bits.ldw.mbaddr = ((dmap->dma_cookie.dmac_laddress &
   2462 	    TXDMA_MBL_MASK) >> TXDMA_MBL_SHIFT);
   2463 
   2464 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2465 	    "==> nxge_map_txdma_channel_cfg_ring: mbox 0x%lx",
   2466 	    dmap->dma_cookie.dmac_laddress));
   2467 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2468 	    "==> nxge_map_txdma_channel_cfg_ring: hmbox $%p "
   2469 	    "mbox $%p",
   2470 	    mboxh_p->bits.ldw.mbaddr, mboxl_p->bits.ldw.mbaddr));
   2471 	tx_ring_p->page_valid.value = 0;
   2472 	tx_ring_p->page_mask_1.value = tx_ring_p->page_mask_2.value = 0;
   2473 	tx_ring_p->page_value_1.value = tx_ring_p->page_value_2.value = 0;
   2474 	tx_ring_p->page_reloc_1.value = tx_ring_p->page_reloc_2.value = 0;
   2475 	tx_ring_p->page_hdl.value = 0;
   2476 
   2477 	tx_ring_p->page_valid.bits.ldw.page0 = 1;
   2478 	tx_ring_p->page_valid.bits.ldw.page1 = 1;
   2479 
   2480 	tx_ring_p->max_burst.value = 0;
   2481 	tx_ring_p->max_burst.bits.ldw.dma_max_burst = TXC_DMA_MAX_BURST_DEFAULT;
   2482 
   2483 	*tx_mbox_p = mboxp;
   2484 
   2485 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2486 	    "<== nxge_map_txdma_channel_cfg_ring"));
   2487 }
   2488 
   2489 /*ARGSUSED*/
   2490 static void
   2491 nxge_unmap_txdma_channel_cfg_ring(p_nxge_t nxgep,
   2492 	p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p)
   2493 {
   2494 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2495 	    "==> nxge_unmap_txdma_channel_cfg_ring: channel %d",
   2496 	    tx_ring_p->tdc));
   2497 
   2498 	KMEM_FREE(tx_mbox_p, sizeof (tx_mbox_t));
   2499 
   2500 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2501 	    "<== nxge_unmap_txdma_channel_cfg_ring"));
   2502 }
   2503 
   2504 /*
   2505  * nxge_map_txdma_channel_buf_ring
   2506  *
   2507  *
   2508  * Arguments:
   2509  * 	nxgep
   2510  * 	channel		The channel to map.
   2511  *	dma_buf_p
   2512  *	tx_desc_p	channel's descriptor ring
   2513  *	num_chunks
   2514  *
   2515  * Notes:
   2516  *
   2517  * NPI/NXGE function calls:
   2518  *	nxge_setup_dma_common()
   2519  *
   2520  * Registers accessed:
   2521  *	none.
   2522  *
   2523  * Context:
   2524  *	Any domain
   2525  */
   2526 static nxge_status_t
   2527 nxge_map_txdma_channel_buf_ring(p_nxge_t nxgep, uint16_t channel,
   2528 	p_nxge_dma_common_t *dma_buf_p,
   2529 	p_tx_ring_t *tx_desc_p, uint32_t num_chunks)
   2530 {
   2531 	p_nxge_dma_common_t 	dma_bufp, tmp_bufp;
   2532 	p_nxge_dma_common_t 	dmap;
   2533 	nxge_os_dma_handle_t	tx_buf_dma_handle;
   2534 	p_tx_ring_t 		tx_ring_p;
   2535 	p_tx_msg_t 		tx_msg_ring;
   2536 	nxge_status_t		status = NXGE_OK;
   2537 	int			ddi_status = DDI_SUCCESS;
   2538 	int			i, j, index;
   2539 	uint32_t		size, bsize;
   2540 	uint32_t 		nblocks, nmsgs;
   2541 	char			qname[TASKQ_NAMELEN];
   2542 
   2543 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2544 	    "==> nxge_map_txdma_channel_buf_ring"));
   2545 
   2546 	dma_bufp = tmp_bufp = *dma_buf_p;
   2547 		NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2548 		" nxge_map_txdma_channel_buf_ring: channel %d to map %d "
   2549 		"chunks bufp $%p",
   2550 		    channel, num_chunks, dma_bufp));
   2551 
   2552 	nmsgs = 0;
   2553 	for (i = 0; i < num_chunks; i++, tmp_bufp++) {
   2554 		nmsgs += tmp_bufp->nblocks;
   2555 		NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2556 		    "==> nxge_map_txdma_channel_buf_ring: channel %d "
   2557 		    "bufp $%p nblocks %d nmsgs %d",
   2558 		    channel, tmp_bufp, tmp_bufp->nblocks, nmsgs));
   2559 	}
   2560 	if (!nmsgs) {
   2561 		NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2562 		    "<== nxge_map_txdma_channel_buf_ring: channel %d "
   2563 		    "no msg blocks",
   2564 		    channel));
   2565 		status = NXGE_ERROR;
   2566 		goto nxge_map_txdma_channel_buf_ring_exit;
   2567 	}
   2568 
   2569 	tx_ring_p = (p_tx_ring_t)
   2570 	    KMEM_ZALLOC(sizeof (tx_ring_t), KM_SLEEP);
   2571 	MUTEX_INIT(&tx_ring_p->lock, NULL, MUTEX_DRIVER,
   2572 	    (void *)nxgep->interrupt_cookie);
   2573 
   2574 	(void) atomic_swap_32(&tx_ring_p->tx_ring_offline, NXGE_TX_RING_ONLINE);
   2575 	tx_ring_p->tx_ring_busy = B_FALSE;
   2576 	tx_ring_p->nxgep = nxgep;
   2577 	tx_ring_p->tx_ring_handle = (mac_ring_handle_t)NULL;
   2578 	(void) snprintf(qname, TASKQ_NAMELEN, "tx_%d_%d",
   2579 	    nxgep->instance, channel);
   2580 	tx_ring_p->taskq = ddi_taskq_create(nxgep->dip, qname, 1,
   2581 	    TASKQ_DEFAULTPRI, 0);
   2582 	if (tx_ring_p->taskq == NULL) {
   2583 		goto nxge_map_txdma_channel_buf_ring_fail1;
   2584 	}
   2585 
   2586 	/*
   2587 	 * Allocate transmit message rings and handles for packets
   2588 	 * not to be copied to premapped buffers.
   2589 	 */
   2590 	size = nmsgs * sizeof (tx_msg_t);
   2591 	tx_msg_ring = KMEM_ZALLOC(size, KM_SLEEP);
   2592 	for (i = 0; i < nmsgs; i++) {
   2593 		ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr,
   2594 		    DDI_DMA_DONTWAIT, 0,
   2595 		    &tx_msg_ring[i].dma_handle);
   2596 		if (ddi_status != DDI_SUCCESS) {
   2597 			status |= NXGE_DDI_FAILED;
   2598 			break;
   2599 		}
   2600 	}
   2601 	if (i < nmsgs) {
   2602 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   2603 		    "Allocate handles failed."));
   2604 		goto nxge_map_txdma_channel_buf_ring_fail1;
   2605 	}
   2606 
   2607 	tx_ring_p->tdc = channel;
   2608 	tx_ring_p->tx_msg_ring = tx_msg_ring;
   2609 	tx_ring_p->tx_ring_size = nmsgs;
   2610 	tx_ring_p->num_chunks = num_chunks;
   2611 	if (!nxge_tx_intr_thres) {
   2612 		nxge_tx_intr_thres = tx_ring_p->tx_ring_size/4;
   2613 	}
   2614 	tx_ring_p->tx_wrap_mask = tx_ring_p->tx_ring_size - 1;
   2615 	tx_ring_p->rd_index = 0;
   2616 	tx_ring_p->wr_index = 0;
   2617 	tx_ring_p->ring_head.value = 0;
   2618 	tx_ring_p->ring_kick_tail.value = 0;
   2619 	tx_ring_p->descs_pending = 0;
   2620 
   2621 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2622 	    "==> nxge_map_txdma_channel_buf_ring: channel %d "
   2623 	    "actual tx desc max %d nmsgs %d "
   2624 	    "(config nxge_tx_ring_size %d)",
   2625 	    channel, tx_ring_p->tx_ring_size, nmsgs,
   2626 	    nxge_tx_ring_size));
   2627 
   2628 	/*
   2629 	 * Map in buffers from the buffer pool.
   2630 	 */
   2631 	index = 0;
   2632 	bsize = dma_bufp->block_size;
   2633 
   2634 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel_buf_ring: "
   2635 	    "dma_bufp $%p tx_rng_p $%p "
   2636 	    "tx_msg_rng_p $%p bsize %d",
   2637 	    dma_bufp, tx_ring_p, tx_msg_ring, bsize));
   2638 
   2639 	tx_buf_dma_handle = dma_bufp->dma_handle;
   2640 	for (i = 0; i < num_chunks; i++, dma_bufp++) {
   2641 		bsize = dma_bufp->block_size;
   2642 		nblocks = dma_bufp->nblocks;
   2643 		NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2644 		    "==> nxge_map_txdma_channel_buf_ring: dma chunk %d "
   2645 		    "size %d dma_bufp $%p",
   2646 		    i, sizeof (nxge_dma_common_t), dma_bufp));
   2647 
   2648 		for (j = 0; j < nblocks; j++) {
   2649 			tx_msg_ring[index].buf_dma_handle = tx_buf_dma_handle;
   2650 			dmap = &tx_msg_ring[index++].buf_dma;
   2651 #ifdef TX_MEM_DEBUG
   2652 			NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2653 			    "==> nxge_map_txdma_channel_buf_ring: j %d"
   2654 			    "dmap $%p", i, dmap));
   2655 #endif
   2656 			nxge_setup_dma_common(dmap, dma_bufp, 1,
   2657 			    bsize);
   2658 		}
   2659 	}
   2660 
   2661 	if (i < num_chunks) {
   2662 		status = NXGE_ERROR;
   2663 		goto nxge_map_txdma_channel_buf_ring_fail1;
   2664 	}
   2665 
   2666 	*tx_desc_p = tx_ring_p;
   2667 
   2668 	goto nxge_map_txdma_channel_buf_ring_exit;
   2669 
   2670 nxge_map_txdma_channel_buf_ring_fail1:
   2671 	if (tx_ring_p->taskq) {
   2672 		ddi_taskq_destroy(tx_ring_p->taskq);
   2673 		tx_ring_p->taskq = NULL;
   2674 	}
   2675 
   2676 	index--;
   2677 	for (; index >= 0; index--) {
   2678 		if (tx_msg_ring[index].dma_handle != NULL) {
   2679 			ddi_dma_free_handle(&tx_msg_ring[index].dma_handle);
   2680 		}
   2681 	}
   2682 	MUTEX_DESTROY(&tx_ring_p->lock);
   2683 	KMEM_FREE(tx_msg_ring, size);
   2684 	KMEM_FREE(tx_ring_p, sizeof (tx_ring_t));
   2685 
   2686 	status = NXGE_ERROR;
   2687 
   2688 nxge_map_txdma_channel_buf_ring_exit:
   2689 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2690 	    "<== nxge_map_txdma_channel_buf_ring status 0x%x", status));
   2691 
   2692 	return (status);
   2693 }
   2694 
   2695 /*ARGSUSED*/
   2696 static void
   2697 nxge_unmap_txdma_channel_buf_ring(p_nxge_t nxgep, p_tx_ring_t tx_ring_p)
   2698 {
   2699 	p_tx_msg_t 		tx_msg_ring;
   2700 	p_tx_msg_t 		tx_msg_p;
   2701 	int			i;
   2702 
   2703 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2704 	    "==> nxge_unmap_txdma_channel_buf_ring"));
   2705 	if (tx_ring_p == NULL) {
   2706 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   2707 		    "<== nxge_unmap_txdma_channel_buf_ring: NULL ringp"));
   2708 		return;
   2709 	}
   2710 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2711 	    "==> nxge_unmap_txdma_channel_buf_ring: channel %d",
   2712 	    tx_ring_p->tdc));
   2713 
   2714 	tx_msg_ring = tx_ring_p->tx_msg_ring;
   2715 
   2716 	/*
   2717 	 * Since the serialization thread, timer thread and
   2718 	 * interrupt thread can all call the transmit reclaim,
   2719 	 * the unmapping function needs to acquire the lock
   2720 	 * to free those buffers which were transmitted
   2721 	 * by the hardware already.
   2722 	 */
   2723 	MUTEX_ENTER(&tx_ring_p->lock);
   2724 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
   2725 	    "==> nxge_unmap_txdma_channel_buf_ring (reclaim): "
   2726 	    "channel %d",
   2727 	    tx_ring_p->tdc));
   2728 	(void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0);
   2729 
   2730 	for (i = 0; i < tx_ring_p->tx_ring_size; i++) {
   2731 		tx_msg_p = &tx_msg_ring[i];
   2732 		if (tx_msg_p->tx_message != NULL) {
   2733 			freemsg(tx_msg_p->tx_message);
   2734 			tx_msg_p->tx_message = NULL;
   2735 		}
   2736 	}
   2737 
   2738 	for (i = 0; i < tx_ring_p->tx_ring_size; i++) {
   2739 		if (tx_msg_ring[i].dma_handle != NULL) {
   2740 			ddi_dma_free_handle(&tx_msg_ring[i].dma_handle);
   2741 		}
   2742 		tx_msg_ring[i].dma_handle = NULL;
   2743 	}
   2744 
   2745 	MUTEX_EXIT(&tx_ring_p->lock);
   2746 
   2747 	if (tx_ring_p->taskq) {
   2748 		ddi_taskq_destroy(tx_ring_p->taskq);
   2749 		tx_ring_p->taskq = NULL;
   2750 	}
   2751 
   2752 	MUTEX_DESTROY(&tx_ring_p->lock);
   2753 	KMEM_FREE(tx_msg_ring, sizeof (tx_msg_t) * tx_ring_p->tx_ring_size);
   2754 	KMEM_FREE(tx_ring_p, sizeof (tx_ring_t));
   2755 
   2756 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2757 	    "<== nxge_unmap_txdma_channel_buf_ring"));
   2758 }
   2759 
   2760 static nxge_status_t
   2761 nxge_txdma_hw_start(p_nxge_t nxgep, int channel)
   2762 {
   2763 	p_tx_rings_t 		tx_rings;
   2764 	p_tx_ring_t 		*tx_desc_rings;
   2765 	p_tx_mbox_areas_t 	tx_mbox_areas_p;
   2766 	p_tx_mbox_t		*tx_mbox_p;
   2767 	nxge_status_t		status = NXGE_OK;
   2768 
   2769 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start"));
   2770 
   2771 	tx_rings = nxgep->tx_rings;
   2772 	if (tx_rings == NULL) {
   2773 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   2774 		    "<== nxge_txdma_hw_start: NULL ring pointer"));
   2775 		return (NXGE_ERROR);
   2776 	}
   2777 	tx_desc_rings = tx_rings->rings;
   2778 	if (tx_desc_rings == NULL) {
   2779 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   2780 		    "<== nxge_txdma_hw_start: NULL ring pointers"));
   2781 		return (NXGE_ERROR);
   2782 	}
   2783 
   2784 	NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: "
   2785 	    "tx_rings $%p tx_desc_rings $%p", tx_rings, tx_desc_rings));
   2786 
   2787 	tx_mbox_areas_p = nxgep->tx_mbox_areas_p;
   2788 	tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p;
   2789 
   2790 	status = nxge_txdma_start_channel(nxgep, channel,
   2791 	    (p_tx_ring_t)tx_desc_rings[channel],
   2792 	    (p_tx_mbox_t)tx_mbox_p[channel]);
   2793 	if (status != NXGE_OK) {
   2794 		goto nxge_txdma_hw_start_fail1;
   2795 	}
   2796 
   2797 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: "
   2798 	    "tx_rings $%p rings $%p",
   2799 	    nxgep->tx_rings, nxgep->tx_rings->rings));
   2800 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: "
   2801 	    "tx_rings $%p tx_desc_rings $%p",
   2802 	    nxgep->tx_rings, tx_desc_rings));
   2803 
   2804 	goto nxge_txdma_hw_start_exit;
   2805 
   2806 nxge_txdma_hw_start_fail1:
   2807 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2808 	    "==> nxge_txdma_hw_start: disable "
   2809 	    "(status 0x%x channel %d)", status, channel));
   2810 
   2811 nxge_txdma_hw_start_exit:
   2812 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2813 	    "==> nxge_txdma_hw_start: (status 0x%x)", status));
   2814 
   2815 	return (status);
   2816 }
   2817 
   2818 /*
   2819  * nxge_txdma_start_channel
   2820  *
   2821  *	Start a TDC.
   2822  *
   2823  * Arguments:
   2824  * 	nxgep
   2825  * 	channel		The channel to start.
   2826  * 	tx_ring_p	channel's transmit descriptor ring.
   2827  * 	tx_mbox_p	channel' smailbox.
   2828  *
   2829  * Notes:
   2830  *
   2831  * NPI/NXGE function calls:
   2832  *	nxge_reset_txdma_channel()
   2833  *	nxge_init_txdma_channel_event_mask()
   2834  *	nxge_enable_txdma_channel()
   2835  *
   2836  * Registers accessed:
   2837  *	none directly (see functions above).
   2838  *
   2839  * Context:
   2840  *	Any domain
   2841  */
   2842 static nxge_status_t
   2843 nxge_txdma_start_channel(p_nxge_t nxgep, uint16_t channel,
   2844     p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p)
   2845 
   2846 {
   2847 	nxge_status_t		status = NXGE_OK;
   2848 
   2849 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2850 		"==> nxge_txdma_start_channel (channel %d)", channel));
   2851 	/*
   2852 	 * TXDMA/TXC must be in stopped state.
   2853 	 */
   2854 	(void) nxge_txdma_stop_inj_err(nxgep, channel);
   2855 
   2856 	/*
   2857 	 * Reset TXDMA channel
   2858 	 */
   2859 	tx_ring_p->tx_cs.value = 0;
   2860 	tx_ring_p->tx_cs.bits.ldw.rst = 1;
   2861 	status = nxge_reset_txdma_channel(nxgep, channel,
   2862 			tx_ring_p->tx_cs.value);
   2863 	if (status != NXGE_OK) {
   2864 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   2865 			"==> nxge_txdma_start_channel (channel %d)"
   2866 			" reset channel failed 0x%x", channel, status));
   2867 		goto nxge_txdma_start_channel_exit;
   2868 	}
   2869 
   2870 	/*
   2871 	 * Initialize the TXDMA channel specific FZC control
   2872 	 * configurations. These FZC registers are pertaining
   2873 	 * to each TX channel (i.e. logical pages).
   2874 	 */
   2875 	if (!isLDOMguest(nxgep)) {
   2876 		status = nxge_init_fzc_txdma_channel(nxgep, channel,
   2877 		    tx_ring_p, tx_mbox_p);
   2878 		if (status != NXGE_OK) {
   2879 			goto nxge_txdma_start_channel_exit;
   2880 		}
   2881 	}
   2882 
   2883 	/*
   2884 	 * Initialize the event masks.
   2885 	 */
   2886 	tx_ring_p->tx_evmask.value = 0;
   2887 	status = nxge_init_txdma_channel_event_mask(nxgep,
   2888 	    channel, &tx_ring_p->tx_evmask);
   2889 	if (status != NXGE_OK) {
   2890 		goto nxge_txdma_start_channel_exit;
   2891 	}
   2892 
   2893 	/*
   2894 	 * Load TXDMA descriptors, buffers, mailbox,
   2895 	 * initialise the DMA channels and
   2896 	 * enable each DMA channel.
   2897 	 */
   2898 	status = nxge_enable_txdma_channel(nxgep, channel,
   2899 			tx_ring_p, tx_mbox_p);
   2900 	if (status != NXGE_OK) {
   2901 		goto nxge_txdma_start_channel_exit;
   2902 	}
   2903 
   2904 nxge_txdma_start_channel_exit:
   2905 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_start_channel"));
   2906 
   2907 	return (status);
   2908 }
   2909 
   2910 /*
   2911  * nxge_txdma_stop_channel
   2912  *
   2913  *	Stop a TDC.
   2914  *
   2915  * Arguments:
   2916  * 	nxgep
   2917  * 	channel		The channel to stop.
   2918  * 	tx_ring_p	channel's transmit descriptor ring.
   2919  * 	tx_mbox_p	channel' smailbox.
   2920  *
   2921  * Notes:
   2922  *
   2923  * NPI/NXGE function calls:
   2924  *	nxge_txdma_stop_inj_err()
   2925  *	nxge_reset_txdma_channel()
   2926  *	nxge_init_txdma_channel_event_mask()
   2927  *	nxge_init_txdma_channel_cntl_stat()
   2928  *	nxge_disable_txdma_channel()
   2929  *
   2930  * Registers accessed:
   2931  *	none directly (see functions above).
   2932  *
   2933  * Context:
   2934  *	Any domain
   2935  */
   2936 /*ARGSUSED*/
   2937 static nxge_status_t
   2938 nxge_txdma_stop_channel(p_nxge_t nxgep, uint16_t channel)
   2939 {
   2940 	p_tx_ring_t tx_ring_p;
   2941 	int status = NXGE_OK;
   2942 
   2943 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   2944 	    "==> nxge_txdma_stop_channel: channel %d", channel));
   2945 
   2946 	/*
   2947 	 * Stop (disable) TXDMA and TXC (if stop bit is set
   2948 	 * and STOP_N_GO bit not set, the TXDMA reset state will
   2949 	 * not be set if reset TXDMA.
   2950 	 */
   2951 	(void) nxge_txdma_stop_inj_err(nxgep, channel);
   2952 
   2953 	if (nxgep->tx_rings == NULL) {
   2954 		status = NXGE_ERROR;
   2955 		goto nxge_txdma_stop_channel_exit;
   2956 	}
   2957 
   2958 	tx_ring_p = nxgep->tx_rings->rings[channel];
   2959 	if (tx_ring_p == NULL) {
   2960 		status = NXGE_ERROR;
   2961 		goto nxge_txdma_stop_channel_exit;
   2962 	}
   2963 
   2964 	/*
   2965 	 * Reset TXDMA channel
   2966 	 */
   2967 	tx_ring_p->tx_cs.value = 0;
   2968 	tx_ring_p->tx_cs.bits.ldw.rst = 1;
   2969 	status = nxge_reset_txdma_channel(nxgep, channel,
   2970 	    tx_ring_p->tx_cs.value);
   2971 	if (status != NXGE_OK) {
   2972 		goto nxge_txdma_stop_channel_exit;
   2973 	}
   2974 
   2975 #ifdef HARDWARE_REQUIRED
   2976 	/* Set up the interrupt event masks. */
   2977 	tx_ring_p->tx_evmask.value = 0;
   2978 	status = nxge_init_txdma_channel_event_mask(nxgep,
   2979 	    channel, &tx_ring_p->tx_evmask);
   2980 	if (status != NXGE_OK) {
   2981 		goto nxge_txdma_stop_channel_exit;
   2982 	}
   2983 
   2984 	/* Initialize the DMA control and status register */
   2985 	tx_ring_p->tx_cs.value = TX_ENT_MSK_MK_ALL;
   2986 	status = nxge_init_txdma_channel_cntl_stat(nxgep, channel,
   2987 	    tx_ring_p->tx_cs.value);
   2988 	if (status != NXGE_OK) {
   2989 		goto nxge_txdma_stop_channel_exit;
   2990 	}
   2991 
   2992 	tx_mbox_p = nxgep->tx_mbox_areas_p->txmbox_areas_p[channel];
   2993 
   2994 	/* Disable channel */
   2995 	status = nxge_disable_txdma_channel(nxgep, channel,
   2996 	    tx_ring_p, tx_mbox_p);
   2997 	if (status != NXGE_OK) {
   2998 		goto nxge_txdma_start_channel_exit;
   2999 	}
   3000 
   3001 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
   3002 	    "==> nxge_txdma_stop_channel: event done"));
   3003 
   3004 #endif
   3005 
   3006 nxge_txdma_stop_channel_exit:
   3007 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_stop_channel"));
   3008 	return (status);
   3009 }
   3010 
   3011 /*
   3012  * nxge_txdma_get_ring
   3013  *
   3014  *	Get the ring for a TDC.
   3015  *
   3016  * Arguments:
   3017  * 	nxgep
   3018  * 	channel
   3019  *
   3020  * Notes:
   3021  *
   3022  * NPI/NXGE function calls:
   3023  *
   3024  * Registers accessed:
   3025  *
   3026  * Context:
   3027  *	Any domain
   3028  */
   3029 static p_tx_ring_t
   3030 nxge_txdma_get_ring(p_nxge_t nxgep, uint16_t channel)
   3031 {
   3032 	nxge_grp_set_t *set = &nxgep->tx_set;
   3033 	int tdc;
   3034 
   3035 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_get_ring"));
   3036 
   3037 	if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) {
   3038 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   3039 		    "<== nxge_txdma_get_ring: NULL ring pointer(s)"));
   3040 		goto return_null;
   3041 	}
   3042 
   3043 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   3044 		if ((1 << tdc) & set->owned.map) {
   3045 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   3046 			if (ring) {
   3047 				if (channel == ring->tdc) {
   3048 					NXGE_DEBUG_MSG((nxgep, TX_CTL,
   3049 					    "<== nxge_txdma_get_ring: "
   3050 					    "tdc %d ring $%p", tdc, ring));
   3051 					return (ring);
   3052 				}
   3053 			}
   3054 		}
   3055 	}
   3056 
   3057 return_null:
   3058 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_get_ring: "
   3059 	    "ring not found"));
   3060 
   3061 	return (NULL);
   3062 }
   3063 
   3064 /*
   3065  * nxge_txdma_get_mbox
   3066  *
   3067  *	Get the mailbox for a TDC.
   3068  *
   3069  * Arguments:
   3070  * 	nxgep
   3071  * 	channel
   3072  *
   3073  * Notes:
   3074  *
   3075  * NPI/NXGE function calls:
   3076  *
   3077  * Registers accessed:
   3078  *
   3079  * Context:
   3080  *	Any domain
   3081  */
   3082 static p_tx_mbox_t
   3083 nxge_txdma_get_mbox(p_nxge_t nxgep, uint16_t channel)
   3084 {
   3085 	nxge_grp_set_t *set = &nxgep->tx_set;
   3086 	int tdc;
   3087 
   3088 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_get_mbox"));
   3089 
   3090 	if (nxgep->tx_mbox_areas_p == 0 ||
   3091 	    nxgep->tx_mbox_areas_p->txmbox_areas_p == 0) {
   3092 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   3093 		    "<== nxge_txdma_get_mbox: NULL mailbox pointer(s)"));
   3094 		goto return_null;
   3095 	}
   3096 
   3097 	if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) {
   3098 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   3099 		    "<== nxge_txdma_get_mbox: NULL ring pointer(s)"));
   3100 		goto return_null;
   3101 	}
   3102 
   3103 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   3104 		if ((1 << tdc) & set->owned.map) {
   3105 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   3106 			if (ring) {
   3107 				if (channel == ring->tdc) {
   3108 					tx_mbox_t *mailbox = nxgep->
   3109 					    tx_mbox_areas_p->
   3110 					    txmbox_areas_p[tdc];
   3111 					NXGE_DEBUG_MSG((nxgep, TX_CTL,
   3112 					    "<== nxge_txdma_get_mbox: tdc %d "
   3113 					    "ring $%p", tdc, mailbox));
   3114 					return (mailbox);
   3115 				}
   3116 			}
   3117 		}
   3118 	}
   3119 
   3120 return_null:
   3121 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_get_mbox: "
   3122 	    "mailbox not found"));
   3123 
   3124 	return (NULL);
   3125 }
   3126 
   3127 /*
   3128  * nxge_tx_err_evnts
   3129  *
   3130  *	Recover a TDC.
   3131  *
   3132  * Arguments:
   3133  * 	nxgep
   3134  * 	index	The index to the TDC ring.
   3135  * 	ldvp	Used to get the channel number ONLY.
   3136  * 	cs	A copy of the bits from TX_CS.
   3137  *
   3138  * Notes:
   3139  *	Calling tree:
   3140  *	 nxge_tx_intr()
   3141  *
   3142  * NPI/NXGE function calls:
   3143  *	npi_txdma_ring_error_get()
   3144  *	npi_txdma_inj_par_error_get()
   3145  *	nxge_txdma_fatal_err_recover()
   3146  *
   3147  * Registers accessed:
   3148  *	TX_RNG_ERR_LOGH	DMC+0x40048 Transmit Ring Error Log High
   3149  *	TX_RNG_ERR_LOGL DMC+0x40050 Transmit Ring Error Log Low
   3150  *	TDMC_INJ_PAR_ERR (FZC_DMC + 0x45040) TDMC Inject Parity Error
   3151  *
   3152  * Context:
   3153  *	Any domain	XXX Remove code which accesses TDMC_INJ_PAR_ERR.
   3154  */
   3155 /*ARGSUSED*/
   3156 static nxge_status_t
   3157 nxge_tx_err_evnts(p_nxge_t nxgep, uint_t index, p_nxge_ldv_t ldvp, tx_cs_t cs)
   3158 {
   3159 	npi_handle_t		handle;
   3160 	npi_status_t		rs;
   3161 	uint8_t			channel;
   3162 	p_tx_ring_t 		*tx_rings;
   3163 	p_tx_ring_t 		tx_ring_p;
   3164 	p_nxge_tx_ring_stats_t	tdc_stats;
   3165 	boolean_t		txchan_fatal = B_FALSE;
   3166 	nxge_status_t		status = NXGE_OK;
   3167 	tdmc_inj_par_err_t	par_err;
   3168 	uint32_t		value;
   3169 
   3170 	NXGE_DEBUG_MSG((nxgep, TX2_CTL, "==> nxge_tx_err_evnts"));
   3171 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   3172 	channel = ldvp->channel;
   3173 
   3174 	tx_rings = nxgep->tx_rings->rings;
   3175 	tx_ring_p = tx_rings[index];
   3176 	tdc_stats = tx_ring_p->tdc_stats;
   3177 	if ((cs.bits.ldw.pkt_size_err) || (cs.bits.ldw.pref_buf_par_err) ||
   3178 	    (cs.bits.ldw.nack_pref) || (cs.bits.ldw.nack_pkt_rd) ||
   3179 	    (cs.bits.ldw.conf_part_err) || (cs.bits.ldw.pkt_prt_err)) {
   3180 		if ((rs = npi_txdma_ring_error_get(handle, channel,
   3181 		    &tdc_stats->errlog)) != NPI_SUCCESS)
   3182 			return (NXGE_ERROR | rs);
   3183 	}
   3184 
   3185 	if (cs.bits.ldw.mbox_err) {
   3186 		tdc_stats->mbox_err++;
   3187 		NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
   3188 		    NXGE_FM_EREPORT_TDMC_MBOX_ERR);
   3189 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3190 		    "==> nxge_tx_err_evnts(channel %d): "
   3191 		    "fatal error: mailbox", channel));
   3192 		txchan_fatal = B_TRUE;
   3193 	}
   3194 	if (cs.bits.ldw.pkt_size_err) {
   3195 		tdc_stats->pkt_size_err++;
   3196 		NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
   3197 		    NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR);
   3198 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3199 		    "==> nxge_tx_err_evnts(channel %d): "
   3200 		    "fatal error: pkt_size_err", channel));
   3201 		txchan_fatal = B_TRUE;
   3202 	}
   3203 	if (cs.bits.ldw.tx_ring_oflow) {
   3204 		tdc_stats->tx_ring_oflow++;
   3205 		NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
   3206 		    NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW);
   3207 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3208 		    "==> nxge_tx_err_evnts(channel %d): "
   3209 		    "fatal error: tx_ring_oflow", channel));
   3210 		txchan_fatal = B_TRUE;
   3211 	}
   3212 	if (cs.bits.ldw.pref_buf_par_err) {
   3213 		tdc_stats->pre_buf_par_err++;
   3214 		NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
   3215 		    NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR);
   3216 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3217 		    "==> nxge_tx_err_evnts(channel %d): "
   3218 		    "fatal error: pre_buf_par_err", channel));
   3219 		/* Clear error injection source for parity error */
   3220 		(void) npi_txdma_inj_par_error_get(handle, &value);
   3221 		par_err.value = value;
   3222 		par_err.bits.ldw.inject_parity_error &= ~(1 << channel);
   3223 		(void) npi_txdma_inj_par_error_set(handle, par_err.value);
   3224 		txchan_fatal = B_TRUE;
   3225 	}
   3226 	if (cs.bits.ldw.nack_pref) {
   3227 		tdc_stats->nack_pref++;
   3228 		NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
   3229 		    NXGE_FM_EREPORT_TDMC_NACK_PREF);
   3230 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3231 		    "==> nxge_tx_err_evnts(channel %d): "
   3232 		    "fatal error: nack_pref", channel));
   3233 		txchan_fatal = B_TRUE;
   3234 	}
   3235 	if (cs.bits.ldw.nack_pkt_rd) {
   3236 		tdc_stats->nack_pkt_rd++;
   3237 		NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
   3238 		    NXGE_FM_EREPORT_TDMC_NACK_PKT_RD);
   3239 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3240 		    "==> nxge_tx_err_evnts(channel %d): "
   3241 		    "fatal error: nack_pkt_rd", channel));
   3242 		txchan_fatal = B_TRUE;
   3243 	}
   3244 	if (cs.bits.ldw.conf_part_err) {
   3245 		tdc_stats->conf_part_err++;
   3246 		NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
   3247 		    NXGE_FM_EREPORT_TDMC_CONF_PART_ERR);
   3248 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3249 		    "==> nxge_tx_err_evnts(channel %d): "
   3250 		    "fatal error: config_partition_err", channel));
   3251 		txchan_fatal = B_TRUE;
   3252 	}
   3253 	if (cs.bits.ldw.pkt_prt_err) {
   3254 		tdc_stats->pkt_part_err++;
   3255 		NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
   3256 		    NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR);
   3257 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3258 		    "==> nxge_tx_err_evnts(channel %d): "
   3259 		    "fatal error: pkt_prt_err", channel));
   3260 		txchan_fatal = B_TRUE;
   3261 	}
   3262 
   3263 	/* Clear error injection source in case this is an injected error */
   3264 	TXDMA_REG_WRITE64(nxgep->npi_handle, TDMC_INTR_DBG_REG, channel, 0);
   3265 
   3266 	if (txchan_fatal) {
   3267 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3268 		    " nxge_tx_err_evnts: "
   3269 		    " fatal error on channel %d cs 0x%llx\n",
   3270 		    channel, cs.value));
   3271 		status = nxge_txdma_fatal_err_recover(nxgep, channel,
   3272 		    tx_ring_p);
   3273 		if (status == NXGE_OK) {
   3274 			FM_SERVICE_RESTORED(nxgep);
   3275 		}
   3276 	}
   3277 
   3278 	NXGE_DEBUG_MSG((nxgep, TX2_CTL, "<== nxge_tx_err_evnts"));
   3279 
   3280 	return (status);
   3281 }
   3282 
   3283 static nxge_status_t
   3284 nxge_txdma_fatal_err_recover(
   3285 	p_nxge_t nxgep,
   3286 	uint16_t channel,
   3287 	p_tx_ring_t tx_ring_p)
   3288 {
   3289 	npi_handle_t	handle;
   3290 	npi_status_t	rs = NPI_SUCCESS;
   3291 	p_tx_mbox_t	tx_mbox_p;
   3292 	nxge_status_t	status = NXGE_OK;
   3293 
   3294 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fatal_err_recover"));
   3295 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3296 	    "Recovering from TxDMAChannel#%d error...", channel));
   3297 
   3298 	/*
   3299 	 * Stop the dma channel waits for the stop done.
   3300 	 * If the stop done bit is not set, then create
   3301 	 * an error.
   3302 	 */
   3303 
   3304 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   3305 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel stop..."));
   3306 	MUTEX_ENTER(&tx_ring_p->lock);
   3307 	rs = npi_txdma_channel_control(handle, TXDMA_STOP, channel);
   3308 	if (rs != NPI_SUCCESS) {
   3309 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3310 		    "==> nxge_txdma_fatal_err_recover (channel %d): "
   3311 		    "stop failed ", channel));
   3312 		goto fail;
   3313 	}
   3314 
   3315 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel reclaim..."));
   3316 	(void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0);
   3317 
   3318 	/*
   3319 	 * Reset TXDMA channel
   3320 	 */
   3321 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel reset..."));
   3322 	if ((rs = npi_txdma_channel_control(handle, TXDMA_RESET, channel)) !=
   3323 	    NPI_SUCCESS) {
   3324 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3325 		    "==> nxge_txdma_fatal_err_recover (channel %d)"
   3326 		    " reset channel failed 0x%x", channel, rs));
   3327 		goto fail;
   3328 	}
   3329 
   3330 	/*
   3331 	 * Reset the tail (kick) register to 0.
   3332 	 * (Hardware will not reset it. Tx overflow fatal
   3333 	 * error if tail is not set to 0 after reset!
   3334 	 */
   3335 	TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0);
   3336 
   3337 	/* Restart TXDMA channel */
   3338 
   3339 	if (!isLDOMguest(nxgep)) {
   3340 		tx_mbox_p = nxge_txdma_get_mbox(nxgep, channel);
   3341 
   3342 		// XXX This is a problem in HIO!
   3343 		/*
   3344 		 * Initialize the TXDMA channel specific FZC control
   3345 		 * configurations. These FZC registers are pertaining
   3346 		 * to each TX channel (i.e. logical pages).
   3347 		 */
   3348 		NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel restart..."));
   3349 		status = nxge_init_fzc_txdma_channel(nxgep, channel,
   3350 		    tx_ring_p, tx_mbox_p);
   3351 		if (status != NXGE_OK)
   3352 			goto fail;
   3353 	}
   3354 
   3355 	/*
   3356 	 * Initialize the event masks.
   3357 	 */
   3358 	tx_ring_p->tx_evmask.value = 0;
   3359 	status = nxge_init_txdma_channel_event_mask(nxgep, channel,
   3360 	    &tx_ring_p->tx_evmask);
   3361 	if (status != NXGE_OK)
   3362 		goto fail;
   3363 
   3364 	tx_ring_p->wr_index_wrap = B_FALSE;
   3365 	tx_ring_p->wr_index = 0;
   3366 	tx_ring_p->rd_index = 0;
   3367 
   3368 	/*
   3369 	 * Load TXDMA descriptors, buffers, mailbox,
   3370 	 * initialise the DMA channels and
   3371 	 * enable each DMA channel.
   3372 	 */
   3373 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel enable..."));
   3374 	status = nxge_enable_txdma_channel(nxgep, channel,
   3375 	    tx_ring_p, tx_mbox_p);
   3376 	MUTEX_EXIT(&tx_ring_p->lock);
   3377 	if (status != NXGE_OK)
   3378 		goto fail;
   3379 
   3380 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3381 	    "Recovery Successful, TxDMAChannel#%d Restored",
   3382 	    channel));
   3383 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fatal_err_recover"));
   3384 
   3385 	return (NXGE_OK);
   3386 
   3387 fail:
   3388 	MUTEX_EXIT(&tx_ring_p->lock);
   3389 
   3390 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
   3391 	    "nxge_txdma_fatal_err_recover (channel %d): "
   3392 	    "failed to recover this txdma channel", channel));
   3393 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
   3394 
   3395 	return (status);
   3396 }
   3397 
   3398 /*
   3399  * nxge_tx_port_fatal_err_recover
   3400  *
   3401  *	Attempt to recover from a fatal port error.
   3402  *
   3403  * Arguments:
   3404  * 	nxgep
   3405  *
   3406  * Notes:
   3407  *	How would a guest do this?
   3408  *
   3409  * NPI/NXGE function calls:
   3410  *
   3411  * Registers accessed:
   3412  *
   3413  * Context:
   3414  *	Service domain
   3415  */
   3416 nxge_status_t
   3417 nxge_tx_port_fatal_err_recover(p_nxge_t nxgep)
   3418 {
   3419 	nxge_grp_set_t *set = &nxgep->tx_set;
   3420 	nxge_channel_t tdc;
   3421 
   3422 	tx_ring_t	*ring;
   3423 	tx_mbox_t	*mailbox;
   3424 
   3425 	npi_handle_t	handle;
   3426 	nxge_status_t	status;
   3427 	npi_status_t	rs;
   3428 
   3429 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_tx_port_fatal_err_recover"));
   3430 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3431 	    "Recovering from TxPort error..."));
   3432 
   3433 	if (isLDOMguest(nxgep)) {
   3434 		return (NXGE_OK);
   3435 	}
   3436 
   3437 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
   3438 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   3439 		    "<== nxge_tx_port_fatal_err_recover: not initialized"));
   3440 		return (NXGE_ERROR);
   3441 	}
   3442 
   3443 	if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) {
   3444 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
   3445 		    "<== nxge_tx_port_fatal_err_recover: "
   3446 		    "NULL ring pointer(s)"));
   3447 		return (NXGE_ERROR);
   3448 	}
   3449 
   3450 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   3451 		if ((1 << tdc) & set->owned.map) {
   3452 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   3453 			if (ring)
   3454 				MUTEX_ENTER(&ring->lock);
   3455 		}
   3456 	}
   3457 
   3458 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
   3459 
   3460 	/*
   3461 	 * Stop all the TDCs owned by us.
   3462 	 * (The shared TDCs will have been stopped by their owners.)
   3463 	 */
   3464 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   3465 		if ((1 << tdc) & set->owned.map) {
   3466 			ring = nxgep->tx_rings->rings[tdc];
   3467 			if (ring) {
   3468 				rs = npi_txdma_channel_control
   3469 				    (handle, TXDMA_STOP, tdc);
   3470 				if (rs != NPI_SUCCESS) {
   3471 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3472 					    "nxge_tx_port_fatal_err_recover "
   3473 					    "(channel %d): stop failed ", tdc));
   3474 					goto fail;
   3475 				}
   3476 			}
   3477 		}
   3478 	}
   3479 
   3480 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "Reclaiming all TDCs..."));
   3481 
   3482 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   3483 		if ((1 << tdc) & set->owned.map) {
   3484 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   3485 			if (ring) {
   3486 				(void) nxge_txdma_reclaim(nxgep, ring, 0);
   3487 			}
   3488 		}
   3489 	}
   3490 
   3491 	/*
   3492 	 * Reset all the TDCs.
   3493 	 */
   3494 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "Resetting all TDCs..."));
   3495 
   3496 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   3497 		if ((1 << tdc) & set->owned.map) {
   3498 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   3499 			if (ring) {
   3500 				if ((rs = npi_txdma_channel_control
   3501 				    (handle, TXDMA_RESET, tdc))
   3502 				    != NPI_SUCCESS) {
   3503 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
   3504 					    "nxge_tx_port_fatal_err_recover "
   3505 					    "(channel %d) reset channel "
   3506 					    "failed 0x%x", tdc, rs));
   3507 					goto fail;
   3508 				}
   3509 			}
   3510 			/*
   3511 			 * Reset the tail (kick) register to 0.
   3512 			 * (Hardware will not reset it. Tx overflow fatal
   3513 			 * error if tail is not set to 0 after reset!
   3514 			 */
   3515 			TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, tdc, 0);
   3516 		}
   3517 	}
   3518 
   3519 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "Restarting all TDCs..."));
   3520 
   3521 	/* Restart all the TDCs */
   3522 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   3523 		if ((1 << tdc) & set->owned.map) {
   3524 			ring = nxgep->tx_rings->rings[tdc];
   3525 			if (ring) {
   3526 				mailbox = nxge_txdma_get_mbox(nxgep, tdc);
   3527 				status = nxge_init_fzc_txdma_channel(nxgep, tdc,
   3528 				    ring, mailbox);
   3529 				ring->tx_evmask.value = 0;
   3530 				/*
   3531 				 * Initialize the event masks.
   3532 				 */
   3533 				status = nxge_init_txdma_channel_event_mask
   3534 				    (nxgep, tdc, &ring->tx_evmask);
   3535 
   3536 				ring->wr_index_wrap = B_FALSE;
   3537 				ring->wr_index = 0;
   3538 				ring->rd_index = 0;
   3539 
   3540 				if (status != NXGE_OK)
   3541 					goto fail;
   3542 				if (status != NXGE_OK)
   3543 					goto fail;
   3544 			}
   3545 		}
   3546 	}
   3547 
   3548 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "Re-enabling all TDCs..."));
   3549 
   3550 	/* Re-enable all the TDCs */
   3551 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   3552 		if ((1 << tdc) & set->owned.map) {
   3553 			ring = nxgep->tx_rings->rings[tdc];
   3554 			if (ring) {
   3555 				mailbox = nxge_txdma_get_mbox(nxgep, tdc);
   3556 				status = nxge_enable_txdma_channel(nxgep, tdc,
   3557 				    ring, mailbox);
   3558 				if (status != NXGE_OK)
   3559 					goto fail;
   3560 			}
   3561 		}
   3562 	}
   3563 
   3564 	/*
   3565 	 * Unlock all the TDCs.
   3566 	 */
   3567 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   3568 		if ((1 << tdc) & set->owned.map) {
   3569 			tx_ring_t *ring = nxgep->tx_rings->rings[tdc];
   3570 			if (ring)
   3571 				MUTEX_EXIT(&ring->lock);
   3572 		}
   3573 	}
   3574 
   3575 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Tx port recovery succeeded"));
   3576 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_port_fatal_err_recover"));
   3577 
   3578 	return (NXGE_OK);
   3579 
   3580 fail:
   3581 	for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) {
   3582 		if ((1 << tdc) & set->owned.map) {
   3583 			ring = nxgep->tx_rings->rings[tdc];
   3584 			if (ring)
   3585 				MUTEX_EXIT(&ring->lock);
   3586 		}
   3587 	}
   3588 
   3589 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Tx port recovery failed"));
   3590 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_port_fatal_err_recover"));
   3591 
   3592 	return (status);
   3593 }
   3594 
   3595 /*
   3596  * nxge_txdma_inject_err
   3597  *
   3598  *	Inject an error into a TDC.
   3599  *
   3600  * Arguments:
   3601  * 	nxgep
   3602  * 	err_id	The error to inject.
   3603  * 	chan	The channel to inject into.
   3604  *
   3605  * Notes:
   3606  *	This is called from nxge_main.c:nxge_err_inject()
   3607  *	Has this ioctl ever been used?
   3608  *
   3609  * NPI/NXGE function calls:
   3610  *	npi_txdma_inj_par_error_get()
   3611  *	npi_txdma_inj_par_error_set()
   3612  *
   3613  * Registers accessed:
   3614  *	TDMC_INJ_PAR_ERR (FZC_DMC + 0x45040) TDMC Inject Parity Error
   3615  *	TDMC_INTR_DBG	DMC + 0x40060 Transmit DMA Interrupt Debug
   3616  *	TDMC_INTR_DBG	DMC + 0x40060 Transmit DMA Interrupt Debug
   3617  *
   3618  * Context:
   3619  *	Service domain
   3620  */
   3621 void
   3622 nxge_txdma_inject_err(p_nxge_t nxgep, uint32_t err_id, uint8_t chan)
   3623 {
   3624 	tdmc_intr_dbg_t		tdi;
   3625 	tdmc_inj_par_err_t	par_err;
   3626 	uint32_t		value;
   3627 	npi_handle_t		handle;
   3628 
   3629 	switch (err_id) {
   3630 
   3631 	case NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR:
   3632 		handle = NXGE_DEV_NPI_HANDLE(nxgep);
   3633 		/* Clear error injection source for parity error */
   3634 		(void) npi_txdma_inj_par_error_get(handle, &value);
   3635 		par_err.value = value;
   3636 		par_err.bits.ldw.inject_parity_error &= ~(1 << chan);
   3637 		(void) npi_txdma_inj_par_error_set(handle, par_err.value);
   3638 
   3639 		par_err.bits.ldw.inject_parity_error = (1 << chan);
   3640 		(void) npi_txdma_inj_par_error_get(handle, &value);
   3641 		par_err.value = value;
   3642 		par_err.bits.ldw.inject_parity_error |= (1 << chan);
   3643 		cmn_err(CE_NOTE, "!Write 0x%llx to TDMC_INJ_PAR_ERR_REG\n",
   3644 		    (unsigned long long)par_err.value);
   3645 		(void) npi_txdma_inj_par_error_set(handle, par_err.value);
   3646 		break;
   3647 
   3648 	case NXGE_FM_EREPORT_TDMC_MBOX_ERR:
   3649 	case NXGE_FM_EREPORT_TDMC_NACK_PREF:
   3650 	case NXGE_FM_EREPORT_TDMC_NACK_PKT_RD:
   3651 	case NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR:
   3652 	case NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW:
   3653 	case NXGE_FM_EREPORT_TDMC_CONF_PART_ERR:
   3654 	case NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR:
   3655 		TXDMA_REG_READ64(nxgep->npi_handle, TDMC_INTR_DBG_REG,
   3656 		    chan, &tdi.value);
   3657 		if (err_id == NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR)
   3658 			tdi.bits.ldw.pref_buf_par_err = 1;
   3659 		else if (err_id == NXGE_FM_EREPORT_TDMC_MBOX_ERR)
   3660 			tdi.bits.ldw.mbox_err = 1;
   3661 		else if (err_id == NXGE_FM_EREPORT_TDMC_NACK_PREF)
   3662 			tdi.bits.ldw.nack_pref = 1;
   3663 		else if (err_id == NXGE_FM_EREPORT_TDMC_NACK_PKT_RD)
   3664 			tdi.bits.ldw.nack_pkt_rd = 1;
   3665 		else if (err_id == NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR)
   3666 			tdi.bits.ldw.pkt_size_err = 1;
   3667 		else if (err_id == NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW)
   3668 			tdi.bits.ldw.tx_ring_oflow = 1;
   3669 		else if (err_id == NXGE_FM_EREPORT_TDMC_CONF_PART_ERR)
   3670 			tdi.bits.ldw.conf_part_err = 1;
   3671 		else if (err_id == NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR)
   3672 			tdi.bits.ldw.pkt_part_err = 1;
   3673 #if defined(__i386)
   3674 		cmn_err(CE_NOTE, "!Write 0x%llx to TDMC_INTR_DBG_REG\n",
   3675 		    tdi.value);
   3676 #else
   3677 		cmn_err(CE_NOTE, "!Write 0x%lx to TDMC_INTR_DBG_REG\n",
   3678 		    tdi.value);
   3679 #endif
   3680 		TXDMA_REG_WRITE64(nxgep->npi_handle, TDMC_INTR_DBG_REG,
   3681 		    chan, tdi.value);
   3682 
   3683 		break;
   3684 	}
   3685 }
   3686