xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_txc.c (revision 1a2d662a91cee3bf82f41cd47c7ae6f3825d9db2)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/nxge/nxge_impl.h>
27 #include <sys/nxge/nxge_txc.h>
28 
29 static nxge_status_t
30 nxge_txc_handle_port_errors(p_nxge_t, uint32_t);
31 static void
32 nxge_txc_inject_port_err(uint8_t, txc_int_stat_dbg_t *,
33     uint8_t istats);
34 extern nxge_status_t nxge_tx_port_fatal_err_recover(p_nxge_t);
35 
36 nxge_status_t
37 nxge_txc_init(p_nxge_t nxgep)
38 {
39 	uint8_t			port;
40 	npi_handle_t		handle;
41 	npi_status_t		rs = NPI_SUCCESS;
42 
43 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
44 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
45 
46 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_init: portn %d", port));
47 
48 	/*
49 	 * Enable the TXC controller.
50 	 */
51 	if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) {
52 		goto fail;
53 	}
54 
55 	/* Enable this port within the TXC. */
56 	if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) {
57 		goto fail;
58 	}
59 
60 	/* Bind DMA channels to this port. */
61 	if ((rs = npi_txc_port_dma_enable(handle, port,
62 	    TXDMA_PORT_BITMAP(nxgep))) != NPI_SUCCESS) {
63 		goto fail;
64 	}
65 
66 	/* Unmask all TXC interrupts */
67 	npi_txc_global_imask_set(handle, port, 0);
68 
69 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_init: portn %d", port));
70 
71 	return (NXGE_OK);
72 fail:
73 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
74 	    "nxge_txc_init: Failed to initialize txc on port %d",
75 	    port));
76 
77 	return (NXGE_ERROR | rs);
78 }
79 
80 nxge_status_t
81 nxge_txc_uninit(p_nxge_t nxgep)
82 {
83 	uint8_t			port;
84 	npi_handle_t		handle;
85 	npi_status_t		rs = NPI_SUCCESS;
86 
87 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
88 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
89 
90 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_uninit: portn %d", port));
91 
92 	/*
93 	 * disable the TXC controller.
94 	 */
95 	if ((rs = npi_txc_global_disable(handle)) != NPI_SUCCESS) {
96 		goto fail;
97 	}
98 
99 	/* disable this port within the TXC. */
100 	if ((rs = npi_txc_port_disable(handle, port)) != NPI_SUCCESS) {
101 		goto fail;
102 	}
103 
104 	/* unbind DMA channels to this port. */
105 	if ((rs = npi_txc_port_dma_enable(handle, port, 0)) != NPI_SUCCESS) {
106 		goto fail;
107 	}
108 
109 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_uninit: portn %d", port));
110 
111 	return (NXGE_OK);
112 fail:
113 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
114 	    "nxge_txc_init: Failed to initialize txc on port %d",
115 	    port));
116 
117 	return (NXGE_ERROR | rs);
118 }
119 
120 /*
121  * nxge_txc_tdc_bind
122  *
123  *	Bind a TDC to a port.
124  *
125  * Arguments:
126  *	nxgep
127  *	channel		The channel to bind.
128  *
129  * Notes:
130  *
131  * NPI/NXGE function calls:
132  *	npi_txc_control()
133  *	npi_txc_global_imask_set()
134  *	npi_txc_port_dma_enable()
135  *
136  * Registers accessed:
137  *	TXC_CONTROL
138  *	TXC_PORT_DMA
139  *	TXC_INT_MASK
140  *
141  * Context:
142  *	Service domain
143  */
144 nxge_status_t
145 nxge_txc_tdc_bind(
146 	p_nxge_t nxgep,
147 	int channel)
148 {
149 	uint8_t		port;
150 	uint64_t	bitmap;
151 	npi_handle_t	handle;
152 	npi_status_t	rs = NPI_SUCCESS;
153 	txc_control_t	txc_control;
154 
155 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
156 
157 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
158 	    "==> nxge_txc_tdc_bind(port %d, channel %d)", port, channel));
159 
160 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
161 
162 	/* Get the current value of TXC_CONTROL. */
163 	(void) npi_txc_control(handle, OP_GET, &txc_control);
164 
165 	/* Mask all TXC interrupts for <port>. */
166 	if (txc_control.value & (1 << port)) {
167 		npi_txc_global_imask_set(handle, port, TXC_INT_MASK_IVAL);
168 	}
169 
170 	/* Bind <channel> to <port>. */
171 	/* Read in the old bitmap. */
172 	TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port,
173 	    &bitmap);
174 
175 	if (bitmap & (1 << channel)) {
176 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
177 		    "nxge_txc_tdc_bind: channel %d already bound on port %d",
178 		    channel, port));
179 	} else {
180 		/* Bind the new channel. */
181 		bitmap |= (1 << channel);
182 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
183 		    "==> nxge_txc_tdc_bind(): bitmap = %lx", bitmap));
184 
185 		/* Write out the new bitmap. */
186 		if ((rs = npi_txc_port_dma_enable(handle, port,
187 		    (uint32_t)bitmap)) != NPI_SUCCESS) {
188 			goto fail;
189 		}
190 	}
191 
192 	/* Enable this port, if necessary. */
193 	if (!(txc_control.value & (1 << port))) {
194 		if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) {
195 			goto fail;
196 		}
197 	}
198 
199 	/*
200 	 * Enable the TXC controller, if necessary.
201 	 */
202 	if (txc_control.bits.ldw.txc_enabled == 0) {
203 		if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) {
204 			goto fail;
205 		}
206 	}
207 
208 	/* Unmask all TXC interrupts on <port> */
209 	npi_txc_global_imask_set(handle, port, 0);
210 
211 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
212 	    "<== nxge_txc_tdc_bind(port %d, channel %d)", port, channel));
213 
214 	return (NXGE_OK);
215 fail:
216 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
217 	    "nxge_txc_tdc_bind(port %d, channel %d) failed", port, channel));
218 
219 	return (NXGE_ERROR | rs);
220 }
221 
222 /*
223  * nxge_txc_tdc_unbind
224  *
225  *	Unbind a TDC from a port.
226  *
227  * Arguments:
228  *	nxgep
229  *	channel		The channel to unbind.
230  *
231  * Notes:
232  *
233  * NPI/NXGE function calls:
234  *	npi_txc_control()
235  *	npi_txc_global_imask_set()
236  *	npi_txc_port_dma_enable()
237  *
238  * Registers accessed:
239  *	TXC_CONTROL
240  *	TXC_PORT_DMA
241  *	TXC_INT_MASK
242  *
243  * Context:
244  *	Service domain
245  */
246 nxge_status_t
247 nxge_txc_tdc_unbind(
248 	p_nxge_t nxgep,
249 	int channel)
250 {
251 	uint8_t		port;
252 	uint64_t	bitmap;
253 	npi_handle_t	handle;
254 	npi_status_t	rs = NPI_SUCCESS;
255 
256 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
257 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
258 
259 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
260 	    "==> nxge_txc_tdc_unbind(port %d, channel %d)", port, channel));
261 
262 	/* Mask all TXC interrupts for <port>. */
263 	npi_txc_global_imask_set(handle, port, TXC_INT_MASK_IVAL);
264 
265 	/* Unbind <channel>. */
266 	/* Read in the old bitmap. */
267 	TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port,
268 	    &bitmap);
269 
270 	bitmap &= (~(1 << channel));
271 
272 	/* Write out the new bitmap. */
273 	if ((rs = npi_txc_port_dma_enable(handle, port,
274 	    (uint32_t)bitmap)) != NPI_SUCCESS) {
275 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
276 		    "npi_txc_port_dma_enable(%d, %d) failed: %x",
277 		    port, channel, rs));
278 	}
279 
280 	/* Unmask all TXC interrupts on <port> */
281 	if (bitmap)
282 		npi_txc_global_imask_set(handle, port, 0);
283 
284 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
285 	    "<== nxge_txc_tdc_unbind(port %d, channel %d)", port, channel));
286 
287 	return (NXGE_OK);
288 fail:
289 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
290 	    "nxge_txc_tdc_unbind(port %d, channel %d) failed", port, channel));
291 
292 	return (NXGE_ERROR | rs);
293 }
294 
295 void
296 nxge_txc_regs_dump(p_nxge_t nxgep)
297 {
298 	uint32_t		cnt1, cnt2;
299 	npi_handle_t		handle;
300 	txc_control_t		control;
301 	uint32_t		bitmap = 0;
302 
303 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\nTXC dump: func # %d:\n",
304 	    nxgep->function_num));
305 
306 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
307 
308 	(void) npi_txc_control(handle, OP_GET, &control);
309 	(void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap);
310 
311 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port control 0x%0llx",
312 	    (long long)control.value));
313 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port bitmap 0x%x", bitmap));
314 
315 	(void) npi_txc_pkt_xmt_to_mac_get(handle, nxgep->function_num,
316 	    &cnt1, &cnt2);
317 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC bytes to MAC %d "
318 	    "packets to MAC %d",
319 	    cnt1, cnt2));
320 
321 	(void) npi_txc_pkt_stuffed_get(handle, nxgep->function_num,
322 	    &cnt1, &cnt2);
323 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
324 	    "\n\tTXC ass packets %d reorder packets %d",
325 	    cnt1 & 0xffff, cnt2 & 0xffff));
326 
327 	(void) npi_txc_reorder_get(handle, nxgep->function_num, &cnt1);
328 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
329 	    "\n\tTXC reorder resource %d", cnt1 & 0xff));
330 }
331 
332 nxge_status_t
333 nxge_txc_handle_sys_errors(p_nxge_t nxgep)
334 {
335 	npi_handle_t		handle;
336 	txc_int_stat_t		istatus;
337 	uint32_t		err_status;
338 	uint8_t			err_portn;
339 	boolean_t		my_err = B_FALSE;
340 	nxge_status_t		status = NXGE_OK;
341 
342 	handle = nxgep->npi_handle;
343 	npi_txc_global_istatus_get(handle, (txc_int_stat_t *)&istatus.value);
344 	switch (nxgep->mac.portnum) {
345 	case 0:
346 		if (istatus.bits.ldw.port0_int_status) {
347 			my_err = B_TRUE;
348 			err_portn = 0;
349 			err_status = istatus.bits.ldw.port0_int_status;
350 		}
351 		break;
352 	case 1:
353 		if (istatus.bits.ldw.port1_int_status) {
354 			my_err = B_TRUE;
355 			err_portn = 1;
356 			err_status = istatus.bits.ldw.port1_int_status;
357 		}
358 		break;
359 	case 2:
360 		if (istatus.bits.ldw.port2_int_status) {
361 			my_err = B_TRUE;
362 			err_portn = 2;
363 			err_status = istatus.bits.ldw.port2_int_status;
364 		}
365 		break;
366 	case 3:
367 		if (istatus.bits.ldw.port3_int_status) {
368 			my_err = B_TRUE;
369 			err_portn = 3;
370 			err_status = istatus.bits.ldw.port3_int_status;
371 		}
372 		break;
373 	default:
374 		return (NXGE_ERROR);
375 	}
376 	if (my_err) {
377 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
378 		    " nxge_txc_handle_sys_errors: errored port %d",
379 		    err_portn));
380 		status = nxge_txc_handle_port_errors(nxgep, err_status);
381 	}
382 
383 	return (status);
384 }
385 
386 static nxge_status_t
387 nxge_txc_handle_port_errors(p_nxge_t nxgep, uint32_t err_status)
388 {
389 	npi_handle_t		handle;
390 	npi_status_t		rs = NPI_SUCCESS;
391 	p_nxge_txc_stats_t	statsp;
392 	txc_int_stat_t		istatus;
393 	boolean_t		txport_fatal = B_FALSE;
394 	uint8_t			portn;
395 	nxge_status_t		status = NXGE_OK;
396 
397 	handle = nxgep->npi_handle;
398 	statsp = (p_nxge_txc_stats_t)&nxgep->statsp->txc_stats;
399 	portn = nxgep->mac.portnum;
400 	istatus.value = 0;
401 
402 	if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
403 	    (err_status & TXC_INT_STAT_RO_CORR_ERR) ||
404 	    (err_status & TXC_INT_STAT_RO_UNCORR_ERR) ||
405 	    (err_status & TXC_INT_STAT_REORDER_ERR)) {
406 		if ((rs = npi_txc_ro_states_get(handle, portn,
407 		    &statsp->errlog.ro_st)) != NPI_SUCCESS) {
408 			return (NXGE_ERROR | rs);
409 		}
410 
411 		if (err_status & TXC_INT_STAT_RO_CORR_ERR) {
412 			statsp->ro_correct_err++;
413 			NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
414 			    NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR);
415 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
416 			    "nxge_txc_err_evnts: "
417 			    "RO FIFO correctable error"));
418 		}
419 		if (err_status & TXC_INT_STAT_RO_UNCORR_ERR) {
420 			statsp->ro_uncorrect_err++;
421 			NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
422 			    NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR);
423 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
424 			    "nxge_txc_err_evnts: "
425 			    "RO FIFO uncorrectable error"));
426 		}
427 		if (err_status & TXC_INT_STAT_REORDER_ERR) {
428 			statsp->reorder_err++;
429 			NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
430 			    NXGE_FM_EREPORT_TXC_REORDER_ERR);
431 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
432 			    "nxge_txc_err_evnts: "
433 			    "fatal error: Reorder error"));
434 			txport_fatal = B_TRUE;
435 		}
436 
437 		if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
438 		    (err_status & TXC_INT_STAT_RO_CORR_ERR) ||
439 		    (err_status & TXC_INT_STAT_RO_UNCORR_ERR)) {
440 
441 			if ((rs = npi_txc_ro_ecc_state_clr(handle, portn))
442 			    != NPI_SUCCESS)
443 				return (NXGE_ERROR | rs);
444 			/*
445 			 * Making sure that error source is cleared if this is
446 			 * an injected error.
447 			 */
448 			TXC_FZC_CNTL_REG_WRITE64(handle, TXC_ROECC_CTL_REG,
449 			    portn, 0);
450 		}
451 	}
452 
453 	if ((err_status & TXC_INT_STAT_SF_CORR_ERR) ||
454 	    (err_status & TXC_INT_STAT_SF_UNCORR_ERR)) {
455 		if ((rs = npi_txc_sf_states_get(handle, portn,
456 		    &statsp->errlog.sf_st)) != NPI_SUCCESS) {
457 			return (NXGE_ERROR | rs);
458 		}
459 		if (err_status & TXC_INT_STAT_SF_CORR_ERR) {
460 			statsp->sf_correct_err++;
461 			NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
462 			    NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR);
463 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
464 			    "nxge_txc_err_evnts: "
465 			    "SF FIFO correctable error"));
466 		}
467 		if (err_status & TXC_INT_STAT_SF_UNCORR_ERR) {
468 			statsp->sf_uncorrect_err++;
469 			NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
470 			    NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR);
471 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
472 			    "nxge_txc_err_evnts: "
473 			    "SF FIFO uncorrectable error"));
474 		}
475 		if ((rs = npi_txc_sf_ecc_state_clr(handle, portn))
476 		    != NPI_SUCCESS)
477 			return (NXGE_ERROR | rs);
478 		/*
479 		 * Making sure that error source is cleared if this is
480 		 * an injected error.
481 		 */
482 		TXC_FZC_CNTL_REG_WRITE64(handle, TXC_SFECC_CTL_REG, portn, 0);
483 	}
484 
485 	/* Clear corresponding errors */
486 	switch (portn) {
487 	case 0:
488 		istatus.bits.ldw.port0_int_status = err_status;
489 		break;
490 	case 1:
491 		istatus.bits.ldw.port1_int_status = err_status;
492 		break;
493 	case 2:
494 		istatus.bits.ldw.port2_int_status = err_status;
495 		break;
496 	case 3:
497 		istatus.bits.ldw.port3_int_status = err_status;
498 		break;
499 	default:
500 		return (NXGE_ERROR);
501 	}
502 
503 	npi_txc_global_istatus_clear(handle, istatus.value);
504 
505 	if (txport_fatal) {
506 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
507 		    " nxge_txc_handle_port_errors:"
508 		    " fatal Error on Port#%d\n",
509 		    portn));
510 		status = nxge_tx_port_fatal_err_recover(nxgep);
511 		if (status == NXGE_OK) {
512 			FM_SERVICE_RESTORED(nxgep);
513 		}
514 	}
515 
516 	return (status);
517 }
518 
519 void
520 nxge_txc_inject_err(p_nxge_t nxgep, uint32_t err_id)
521 {
522 	txc_int_stat_dbg_t	txcs;
523 	txc_roecc_ctl_t		ro_ecc_ctl;
524 	txc_sfecc_ctl_t		sf_ecc_ctl;
525 	uint8_t			portn = nxgep->mac.portnum;
526 
527 	cmn_err(CE_NOTE, "!TXC error Inject\n");
528 	switch (err_id) {
529 	case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR:
530 	case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR:
531 		ro_ecc_ctl.value = 0;
532 		ro_ecc_ctl.bits.ldw.all_pkts = 1;
533 		ro_ecc_ctl.bits.ldw.second_line_pkt = 1;
534 		if (err_id == NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR)
535 			ro_ecc_ctl.bits.ldw.single_bit_err = 1;
536 		else
537 			ro_ecc_ctl.bits.ldw.double_bit_err = 1;
538 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_ROECC_CTL_REG\n",
539 		    ro_ecc_ctl.value);
540 		TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_ROECC_CTL_REG,
541 		    portn, ro_ecc_ctl.value);
542 		break;
543 	case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR:
544 	case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR:
545 		sf_ecc_ctl.value = 0;
546 		sf_ecc_ctl.bits.ldw.all_pkts = 1;
547 		sf_ecc_ctl.bits.ldw.second_line_pkt = 1;
548 		if (err_id == NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR)
549 			sf_ecc_ctl.bits.ldw.single_bit_err = 1;
550 		else
551 			sf_ecc_ctl.bits.ldw.double_bit_err = 1;
552 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_SFECC_CTL_REG\n",
553 		    sf_ecc_ctl.value);
554 		TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_SFECC_CTL_REG,
555 		    portn, sf_ecc_ctl.value);
556 		break;
557 	case NXGE_FM_EREPORT_TXC_REORDER_ERR:
558 		NXGE_REG_RD64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
559 		    &txcs.value);
560 		nxge_txc_inject_port_err(portn, &txcs,
561 		    TXC_INT_STAT_REORDER_ERR);
562 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_INT_STAT_DBG_REG\n",
563 		    txcs.value);
564 		NXGE_REG_WR64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
565 		    txcs.value);
566 		break;
567 	default:
568 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
569 		    "nxge_txc_inject_err: Unknown err_id"));
570 	}
571 }
572 
573 static void
574 nxge_txc_inject_port_err(uint8_t portn, txc_int_stat_dbg_t *txcs,
575     uint8_t istats)
576 {
577 	switch (portn) {
578 	case 0:
579 		txcs->bits.ldw.port0_int_status |= istats;
580 		break;
581 	case 1:
582 		txcs->bits.ldw.port1_int_status |= istats;
583 		break;
584 	case 2:
585 		txcs->bits.ldw.port2_int_status |= istats;
586 		break;
587 	case 3:
588 		txcs->bits.ldw.port3_int_status |= istats;
589 		break;
590 	default:
591 		;
592 	}
593 }
594