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