xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_fzc.c (revision 52ccf843e173e2a4a657360b0a22853fd413905f)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include	<nxge_impl.h>
29 #include	<npi_mac.h>
30 #include	<npi_rxdma.h>
31 #include	<nxge_hio.h>
32 
33 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
34 static int	nxge_herr2kerr(uint64_t);
35 #endif
36 
37 static nxge_status_t nxge_init_fzc_rdc_pages(p_nxge_t,
38     uint16_t, dma_log_page_t *, dma_log_page_t *);
39 
40 static nxge_status_t nxge_init_fzc_tdc_pages(p_nxge_t,
41     uint16_t, dma_log_page_t *, dma_log_page_t *);
42 
43 /*
44  * The following interfaces are controlled by the
45  * function control registers. Some global registers
46  * are to be initialized by only byt one of the 2/4 functions.
47  * Use the test and set register.
48  */
49 /*ARGSUSED*/
50 nxge_status_t
51 nxge_test_and_set(p_nxge_t nxgep, uint8_t tas)
52 {
53 	npi_handle_t		handle;
54 	npi_status_t		rs = NPI_SUCCESS;
55 
56 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
57 	if ((rs = npi_dev_func_sr_sr_get_set_clear(handle, tas))
58 	    != NPI_SUCCESS) {
59 		return (NXGE_ERROR | rs);
60 	}
61 
62 	return (NXGE_OK);
63 }
64 
65 nxge_status_t
66 nxge_set_fzc_multi_part_ctl(p_nxge_t nxgep, boolean_t mpc)
67 {
68 	npi_handle_t		handle;
69 	npi_status_t		rs = NPI_SUCCESS;
70 
71 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_set_fzc_multi_part_ctl"));
72 
73 	/*
74 	 * In multi-partitioning, the partition manager
75 	 * who owns function zero should set this multi-partition
76 	 * control bit.
77 	 */
78 	if (nxgep->use_partition && nxgep->function_num) {
79 		return (NXGE_ERROR);
80 	}
81 
82 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
83 	if ((rs = npi_fzc_mpc_set(handle, mpc)) != NPI_SUCCESS) {
84 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
85 		    "<== nxge_set_fzc_multi_part_ctl"));
86 		return (NXGE_ERROR | rs);
87 	}
88 
89 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_set_fzc_multi_part_ctl"));
90 
91 	return (NXGE_OK);
92 }
93 
94 nxge_status_t
95 nxge_get_fzc_multi_part_ctl(p_nxge_t nxgep, boolean_t *mpc_p)
96 {
97 	npi_handle_t		handle;
98 	npi_status_t		rs = NPI_SUCCESS;
99 
100 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_get_fzc_multi_part_ctl"));
101 
102 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
103 	if ((rs = npi_fzc_mpc_get(handle, mpc_p)) != NPI_SUCCESS) {
104 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
105 		    "<== nxge_set_fzc_multi_part_ctl"));
106 		return (NXGE_ERROR | rs);
107 	}
108 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_get_fzc_multi_part_ctl"));
109 
110 	return (NXGE_OK);
111 }
112 
113 /*
114  * System interrupt registers that are under function zero
115  * management.
116  */
117 nxge_status_t
118 nxge_fzc_intr_init(p_nxge_t nxgep)
119 {
120 	nxge_status_t	status = NXGE_OK;
121 
122 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_init"));
123 
124 	/* Configure the initial timer resolution */
125 	if ((status = nxge_fzc_intr_tmres_set(nxgep)) != NXGE_OK) {
126 		return (status);
127 	}
128 
129 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
130 		/*
131 		 * Set up the logical device group's logical devices that
132 		 * the group owns.
133 		 */
134 		if ((status = nxge_fzc_intr_ldg_num_set(nxgep)) != NXGE_OK)
135 			goto fzc_intr_init_exit;
136 
137 		/* Configure the system interrupt data */
138 		if ((status = nxge_fzc_intr_sid_set(nxgep)) != NXGE_OK)
139 			goto fzc_intr_init_exit;
140 	}
141 
142 fzc_intr_init_exit:
143 
144 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_init"));
145 
146 	return (status);
147 }
148 
149 nxge_status_t
150 nxge_fzc_intr_ldg_num_set(p_nxge_t nxgep)
151 {
152 	p_nxge_ldg_t	ldgp;
153 	p_nxge_ldv_t	ldvp;
154 	npi_handle_t	handle;
155 	int		i, j;
156 	npi_status_t	rs = NPI_SUCCESS;
157 
158 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_ldg_num_set"));
159 
160 	if (nxgep->ldgvp == NULL) {
161 		return (NXGE_ERROR);
162 	}
163 
164 	ldgp = nxgep->ldgvp->ldgp;
165 	ldvp = nxgep->ldgvp->ldvp;
166 	if (ldgp == NULL || ldvp == NULL) {
167 		return (NXGE_ERROR);
168 	}
169 
170 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
171 
172 	for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) {
173 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
174 		    "==> nxge_fzc_intr_ldg_num_set "
175 		    "<== nxge_f(Neptune): # ldv %d "
176 		    "in group %d", ldgp->nldvs, ldgp->ldg));
177 
178 		for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
179 			rs = npi_fzc_ldg_num_set(handle, ldvp->ldv,
180 			    ldvp->ldg_assigned);
181 			if (rs != NPI_SUCCESS) {
182 				NXGE_DEBUG_MSG((nxgep, INT_CTL,
183 				    "<== nxge_fzc_intr_ldg_num_set failed "
184 				    " rs 0x%x ldv %d ldg %d",
185 				    rs, ldvp->ldv, ldvp->ldg_assigned));
186 				return (NXGE_ERROR | rs);
187 			}
188 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
189 			    "<== nxge_fzc_intr_ldg_num_set OK "
190 			    " ldv %d ldg %d",
191 			    ldvp->ldv, ldvp->ldg_assigned));
192 		}
193 	}
194 
195 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_ldg_num_set"));
196 
197 	return (NXGE_OK);
198 }
199 
200 nxge_status_t
201 nxge_fzc_intr_tmres_set(p_nxge_t nxgep)
202 {
203 	npi_handle_t	handle;
204 	npi_status_t	rs = NPI_SUCCESS;
205 
206 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_tmrese_set"));
207 	if (nxgep->ldgvp == NULL) {
208 		return (NXGE_ERROR);
209 	}
210 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
211 	if ((rs = npi_fzc_ldg_timer_res_set(handle, nxgep->ldgvp->tmres))) {
212 		return (NXGE_ERROR | rs);
213 	}
214 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_tmrese_set"));
215 
216 	return (NXGE_OK);
217 }
218 
219 nxge_status_t
220 nxge_fzc_intr_sid_set(p_nxge_t nxgep)
221 {
222 	npi_handle_t	handle;
223 	p_nxge_ldg_t	ldgp;
224 	fzc_sid_t	sid;
225 	int		i;
226 	npi_status_t	rs = NPI_SUCCESS;
227 
228 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_sid_set"));
229 	if (nxgep->ldgvp == NULL) {
230 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
231 		    "<== nxge_fzc_intr_sid_set: no ldg"));
232 		return (NXGE_ERROR);
233 	}
234 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
235 	ldgp = nxgep->ldgvp->ldgp;
236 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
237 	    "==> nxge_fzc_intr_sid_set: #int %d", nxgep->ldgvp->ldg_intrs));
238 	for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) {
239 		sid.ldg = ldgp->ldg;
240 		sid.niu = B_FALSE;
241 		sid.func = ldgp->func;
242 		sid.vector = ldgp->vector;
243 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
244 		    "==> nxge_fzc_intr_sid_set(%d): func %d group %d "
245 		    "vector %d",
246 		    i, sid.func, sid.ldg, sid.vector));
247 		rs = npi_fzc_sid_set(handle, sid);
248 		if (rs != NPI_SUCCESS) {
249 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
250 			    "<== nxge_fzc_intr_sid_set:failed 0x%x",
251 			    rs));
252 			return (NXGE_ERROR | rs);
253 		}
254 	}
255 
256 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_sid_set"));
257 
258 	return (NXGE_OK);
259 
260 }
261 
262 /*
263  * nxge_init_fzc_rdc
264  *
265  *	Initialize all of a RDC's FZC_DMC registers.
266  *	This is executed by the service domain, on behalf of a
267  *	guest domain, who cannot access these registers.
268  *
269  * Arguments:
270  * 	nxgep
271  * 	channel		The channel to initialize.
272  *
273  * NPI_NXGE function calls:
274  *	nxge_init_fzc_rdc_pages()
275  *
276  * Context:
277  *	Service Domain
278  */
279 /*ARGSUSED*/
280 nxge_status_t
281 nxge_init_fzc_rdc(p_nxge_t nxgep, uint16_t channel)
282 {
283 	nxge_status_t	status = NXGE_OK;
284 
285 	dma_log_page_t	page1, page2;
286 	npi_handle_t	handle;
287 	rdc_red_para_t	red;
288 
289 	/*
290 	 * Initialize the RxDMA channel-specific FZC control
291 	 * registers.
292 	 */
293 
294 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_tdc"));
295 
296 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
297 
298 	/* Reset RXDMA channel */
299 	status = npi_rxdma_cfg_rdc_reset(handle, channel);
300 	if (status != NPI_SUCCESS) {
301 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
302 		    "==> nxge_init_fzc_rdc: npi_rxdma_cfg_rdc_reset(%d) "
303 		    "returned 0x%08x", channel, status));
304 		return (NXGE_ERROR | status);
305 	}
306 
307 	/*
308 	 * These values have been copied from
309 	 * nxge_txdma.c:nxge_map_txdma_channel_cfg_ring().
310 	 */
311 	page1.page_num = 0;
312 	page1.valid = 1;
313 	page1.func_num = nxgep->function_num;
314 	page1.mask = 0;
315 	page1.value = 0;
316 	page1.reloc = 0;
317 
318 	page2.page_num = 1;
319 	page2.valid = 1;
320 	page2.func_num = nxgep->function_num;
321 	page2.mask = 0;
322 	page2.value = 0;
323 	page2.reloc = 0;
324 
325 	if (nxgep->niu_type == N2_NIU) {
326 #if !defined(NIU_HV_WORKAROUND)
327 		status = NXGE_OK;
328 #else
329 		NXGE_DEBUG_MSG((nxgep, RX_CTL,
330 		    "==> nxge_init_fzc_rxdma_channel: N2_NIU - NEED to "
331 		    "set up logical pages"));
332 		/* Initialize the RXDMA logical pages */
333 		status = nxge_init_fzc_rdc_pages(nxgep, channel,
334 		    &page1, &page2);
335 		if (status != NXGE_OK) {
336 			return (status);
337 		}
338 #endif
339 	} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
340 		/* Initialize the RXDMA logical pages */
341 		status = nxge_init_fzc_rdc_pages(nxgep, channel,
342 		    &page1, &page2);
343 		if (status != NXGE_OK) {
344 			return (status);
345 		}
346 	} else {
347 		return (NXGE_ERROR);
348 	}
349 
350 	/*
351 	 * Configure RED parameters
352 	 */
353 	red.value = 0;
354 	red.bits.ldw.win = RXDMA_RED_WINDOW_DEFAULT;
355 	red.bits.ldw.thre =
356 	    (nxgep->nxge_port_rcr_size - RXDMA_RED_LESS_ENTRIES);
357 	red.bits.ldw.win_syn = RXDMA_RED_WINDOW_DEFAULT;
358 	red.bits.ldw.thre_sync =
359 	    (nxgep->nxge_port_rcr_size - RXDMA_RED_LESS_ENTRIES);
360 
361 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
362 	    "==> nxge_init_fzc_rxdma_channel_red(thre_sync %d(%x))",
363 	    red.bits.ldw.thre_sync,
364 	    red.bits.ldw.thre_sync));
365 
366 	status |= npi_rxdma_cfg_wred_param(handle, channel, &red);
367 
368 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_init_fzc_rdc"));
369 
370 	return (status);
371 }
372 
373 /*
374  * nxge_init_fzc_rxdma_channel
375  *
376  *	Initialize all per-channel FZC_DMC registers.
377  *
378  * Arguments:
379  * 	nxgep
380  * 	channel		The channel to start
381  *
382  * NPI_NXGE function calls:
383  *	nxge_init_hv_fzc_rxdma_channel_pages()
384  *	nxge_init_fzc_rxdma_channel_pages()
385  *	nxge_init_fzc_rxdma_channel_red()
386  *
387  * Context:
388  *	Service Domain
389  */
390 /*ARGSUSED*/
391 nxge_status_t
392 nxge_init_fzc_rxdma_channel(p_nxge_t nxgep, uint16_t channel)
393 {
394 	rx_rbr_ring_t		*rbr_ring;
395 	rx_rcr_ring_t		*rcr_ring;
396 
397 	nxge_status_t		status = NXGE_OK;
398 
399 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_init_fzc_rxdma_channel"));
400 
401 	rbr_ring = nxgep->rx_rbr_rings->rbr_rings[channel];
402 	rcr_ring = nxgep->rx_rcr_rings->rcr_rings[channel];
403 
404 	if (nxgep->niu_type == N2_NIU) {
405 #ifndef	NIU_HV_WORKAROUND
406 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
407 		NXGE_DEBUG_MSG((nxgep, RX_CTL,
408 		    "==> nxge_init_fzc_rxdma_channel: N2_NIU - call HV "
409 		    "set up logical pages"));
410 		/* Initialize the RXDMA logical pages */
411 		status = nxge_init_hv_fzc_rxdma_channel_pages(nxgep, channel,
412 		    rbr_ring);
413 		if (status != NXGE_OK) {
414 			return (status);
415 		}
416 #endif
417 		status = NXGE_OK;
418 #else
419 		NXGE_DEBUG_MSG((nxgep, RX_CTL,
420 		    "==> nxge_init_fzc_rxdma_channel: N2_NIU - NEED to "
421 		    "set up logical pages"));
422 		/* Initialize the RXDMA logical pages */
423 		status = nxge_init_fzc_rxdma_channel_pages(nxgep, channel,
424 		    rbr_ring);
425 		if (status != NXGE_OK) {
426 			return (status);
427 		}
428 #endif
429 	} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
430 		/* Initialize the RXDMA logical pages */
431 		status = nxge_init_fzc_rxdma_channel_pages(nxgep,
432 		    channel, rbr_ring);
433 		if (status != NXGE_OK) {
434 			return (status);
435 		}
436 	} else {
437 		return (NXGE_ERROR);
438 	}
439 
440 	/* Configure RED parameters */
441 	status = nxge_init_fzc_rxdma_channel_red(nxgep, channel, rcr_ring);
442 
443 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_init_fzc_rxdma_channel"));
444 	return (status);
445 }
446 
447 /*
448  * nxge_init_fzc_rdc_pages
449  *
450  *	Configure a TDC's logical pages.
451  *
452  *	This function is executed by the service domain, on behalf of
453  *	a guest domain, to whom this RDC has been loaned.
454  *
455  * Arguments:
456  * 	nxgep
457  * 	channel		The channel to initialize.
458  * 	page0		Logical page 0 definition.
459  * 	page1		Logical page 1 definition.
460  *
461  * Notes:
462  *	I think that this function can be called from any
463  *	domain, but I need to check.
464  *
465  * NPI/NXGE function calls:
466  *	hv_niu_tx_logical_page_conf()
467  *	hv_niu_tx_logical_page_info()
468  *
469  * Context:
470  *	Any domain
471  */
472 nxge_status_t
473 nxge_init_fzc_rdc_pages(
474 	p_nxge_t nxgep,
475 	uint16_t channel,
476 	dma_log_page_t *page0,
477 	dma_log_page_t *page1)
478 {
479 	npi_handle_t handle;
480 	npi_status_t rs;
481 
482 	uint64_t page_handle;
483 
484 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
485 	    "==> nxge_init_fzc_txdma_channel_pages"));
486 
487 #ifndef	NIU_HV_WORKAROUND
488 	if (nxgep->niu_type == N2_NIU) {
489 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
490 		    "<== nxge_init_fzc_rdc_pages: "
491 		    "N2_NIU: no need to set rxdma logical pages"));
492 		return (NXGE_OK);
493 	}
494 #else
495 	if (nxgep->niu_type == N2_NIU) {
496 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
497 		    "<== nxge_init_fzc_rdc_pages: "
498 		    "N2_NIU: NEED to set rxdma logical pages"));
499 	}
500 #endif
501 
502 	/*
503 	 * Initialize logical page 1.
504 	 */
505 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
506 	if ((rs = npi_rxdma_cfg_logical_page(handle, channel, page0))
507 	    != NPI_SUCCESS)
508 		return (NXGE_ERROR | rs);
509 
510 	/*
511 	 * Initialize logical page 2.
512 	 */
513 	if ((rs = npi_rxdma_cfg_logical_page(handle, channel, page1))
514 	    != NPI_SUCCESS)
515 		return (NXGE_ERROR | rs);
516 
517 	/*
518 	 * Initialize the page handle.
519 	 * (In the current driver, this is always set to 0.)
520 	 */
521 	page_handle = 0;
522 	rs = npi_rxdma_cfg_logical_page_handle(handle, channel, page_handle);
523 	if (rs == NPI_SUCCESS) {
524 		return (NXGE_OK);
525 	} else {
526 		return (NXGE_ERROR | rs);
527 	}
528 }
529 
530 /*ARGSUSED*/
531 nxge_status_t
532 nxge_init_fzc_rxdma_channel_pages(p_nxge_t nxgep,
533 		uint16_t channel, p_rx_rbr_ring_t rbrp)
534 {
535 	npi_handle_t		handle;
536 	dma_log_page_t		cfg;
537 	npi_status_t		rs = NPI_SUCCESS;
538 
539 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
540 	    "==> nxge_init_fzc_rxdma_channel_pages"));
541 
542 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
543 	/*
544 	 * Initialize logical page 1.
545 	 */
546 	cfg.func_num = nxgep->function_num;
547 	cfg.page_num = 0;
548 	cfg.valid = rbrp->page_valid.bits.ldw.page0;
549 	cfg.value = rbrp->page_value_1.value;
550 	cfg.mask = rbrp->page_mask_1.value;
551 	cfg.reloc = rbrp->page_reloc_1.value;
552 	rs = npi_rxdma_cfg_logical_page(handle, channel,
553 	    (p_dma_log_page_t)&cfg);
554 	if (rs != NPI_SUCCESS) {
555 		return (NXGE_ERROR | rs);
556 	}
557 
558 	/*
559 	 * Initialize logical page 2.
560 	 */
561 	cfg.page_num = 1;
562 	cfg.valid = rbrp->page_valid.bits.ldw.page1;
563 	cfg.value = rbrp->page_value_2.value;
564 	cfg.mask = rbrp->page_mask_2.value;
565 	cfg.reloc = rbrp->page_reloc_2.value;
566 
567 	rs = npi_rxdma_cfg_logical_page(handle, channel, &cfg);
568 	if (rs != NPI_SUCCESS) {
569 		return (NXGE_ERROR | rs);
570 	}
571 
572 	/* Initialize the page handle */
573 	rs = npi_rxdma_cfg_logical_page_handle(handle, channel,
574 	    rbrp->page_hdl.bits.ldw.handle);
575 
576 	if (rs != NPI_SUCCESS) {
577 		return (NXGE_ERROR | rs);
578 	}
579 
580 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
581 	    "<== nxge_init_fzc_rxdma_channel_pages"));
582 
583 	return (NXGE_OK);
584 }
585 
586 /*ARGSUSED*/
587 nxge_status_t
588 nxge_init_fzc_rxdma_channel_red(p_nxge_t nxgep,
589 	uint16_t channel, p_rx_rcr_ring_t rcr_p)
590 {
591 	npi_handle_t		handle;
592 	rdc_red_para_t		red;
593 	npi_status_t		rs = NPI_SUCCESS;
594 
595 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rxdma_channel_red"));
596 
597 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
598 	red.value = 0;
599 	red.bits.ldw.win = RXDMA_RED_WINDOW_DEFAULT;
600 	red.bits.ldw.thre = (rcr_p->comp_size - RXDMA_RED_LESS_ENTRIES);
601 	red.bits.ldw.win_syn = RXDMA_RED_WINDOW_DEFAULT;
602 	red.bits.ldw.thre_sync = (rcr_p->comp_size - RXDMA_RED_LESS_ENTRIES);
603 
604 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
605 	    "==> nxge_init_fzc_rxdma_channel_red(thre_sync %d(%x))",
606 	    red.bits.ldw.thre_sync,
607 	    red.bits.ldw.thre_sync));
608 
609 	rs = npi_rxdma_cfg_wred_param(handle, channel, &red);
610 	if (rs != NPI_SUCCESS) {
611 		return (NXGE_ERROR | rs);
612 	}
613 
614 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
615 	    "<== nxge_init_fzc_rxdma_channel_red"));
616 
617 	return (NXGE_OK);
618 }
619 
620 /*
621  * nxge_init_fzc_tdc
622  *
623  *	Initialize all of a TDC's FZC_DMC registers.
624  *	This is executed by the service domain, on behalf of a
625  *	guest domain, who cannot access these registers.
626  *
627  * Arguments:
628  * 	nxgep
629  * 	channel		The channel to initialize.
630  *
631  * NPI_NXGE function calls:
632  *	nxge_init_fzc_tdc_pages()
633  *	npi_txc_dma_max_burst_set()
634  *
635  * Registers accessed:
636  *	TXC_DMA_MAX_BURST
637  *
638  * Context:
639  *	Service Domain
640  */
641 /*ARGSUSED*/
642 nxge_status_t
643 nxge_init_fzc_tdc(p_nxge_t nxgep, uint16_t channel)
644 {
645 	nxge_status_t	status = NXGE_OK;
646 
647 	dma_log_page_t	page1, page2;
648 	npi_handle_t	handle;
649 
650 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_tdc"));
651 
652 	/*
653 	 * These values have been copied from
654 	 * nxge_txdma.c:nxge_map_txdma_channel_cfg_ring().
655 	 */
656 	page1.page_num = 0;
657 	page1.valid = 1;
658 	page1.func_num = nxgep->function_num;
659 	page1.mask = 0;
660 	page1.value = 0;
661 	page1.reloc = 0;
662 
663 	page1.page_num = 1;
664 	page1.valid = 1;
665 	page1.func_num = nxgep->function_num;
666 	page1.mask = 0;
667 	page1.value = 0;
668 	page1.reloc = 0;
669 
670 #ifdef	NIU_HV_WORKAROUND
671 	if (nxgep->niu_type == N2_NIU) {
672 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
673 		    "==> nxge_init_fzc_txdma_channel "
674 		    "N2_NIU: NEED to set up txdma logical pages"));
675 		/* Initialize the TXDMA logical pages */
676 		(void) nxge_init_fzc_tdc_pages(nxgep, channel,
677 		    &page1, &page2);
678 	}
679 #endif
680 	if (nxgep->niu_type != N2_NIU) {
681 		if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
682 			/* Initialize the TXDMA logical pages */
683 			(void) nxge_init_fzc_tdc_pages(nxgep, channel,
684 			    &page1, &page2);
685 		} else
686 			return (NXGE_ERROR);
687 	}
688 
689 	/*
690 	 * Configure the TXC DMA Max Burst value.
691 	 *
692 	 * PRM.13.5
693 	 *
694 	 * TXC DMA Max Burst. TXC_DMA_MAX (FZC_TXC + 0000016)
695 	 * 19:0		dma_max_burst		RW
696 	 * Max burst value associated with DMA. Used by DRR engine
697 	 * for computing when DMA has gone into deficit.
698 	 */
699 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
700 	(void) npi_txc_dma_max_burst_set(
701 	    handle, channel, TXC_DMA_MAX_BURST_DEFAULT);
702 
703 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_init_fzc_tdc"));
704 
705 	return (status);
706 }
707 
708 /*ARGSUSED*/
709 nxge_status_t
710 nxge_init_fzc_txdma_channel(p_nxge_t nxgep, uint16_t channel,
711 	p_tx_ring_t tx_ring_p, p_tx_mbox_t mbox_p)
712 {
713 	nxge_status_t	status = NXGE_OK;
714 
715 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
716 	    "==> nxge_init_fzc_txdma_channel"));
717 
718 	if (nxgep->niu_type == N2_NIU) {
719 #ifndef	NIU_HV_WORKAROUND
720 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
721 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
722 		    "==> nxge_init_fzc_txdma_channel "
723 		    "N2_NIU: call HV to set up txdma logical pages"));
724 		status = nxge_init_hv_fzc_txdma_channel_pages(nxgep, channel,
725 		    tx_ring_p);
726 		if (status != NXGE_OK) {
727 			return (status);
728 		}
729 #endif
730 		status = NXGE_OK;
731 #else
732 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
733 		    "==> nxge_init_fzc_txdma_channel "
734 		    "N2_NIU: NEED to set up txdma logical pages"));
735 		/* Initialize the TXDMA logical pages */
736 		(void) nxge_init_fzc_txdma_channel_pages(nxgep, channel,
737 		    tx_ring_p);
738 #endif
739 	} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
740 		/* Initialize the TXDMA logical pages */
741 		(void) nxge_init_fzc_txdma_channel_pages(nxgep,
742 		    channel, tx_ring_p);
743 	} else {
744 		return (NXGE_ERROR);
745 	}
746 
747 	/*
748 	 * Configure Transmit DRR Weight parameters
749 	 * (It actually programs the TXC max burst register).
750 	 */
751 	(void) nxge_init_fzc_txdma_channel_drr(nxgep, channel, tx_ring_p);
752 
753 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
754 	    "<== nxge_init_fzc_txdma_channel"));
755 	return (status);
756 }
757 
758 nxge_status_t
759 nxge_init_fzc_common(p_nxge_t nxgep)
760 {
761 	nxge_status_t	status = NXGE_OK;
762 
763 	(void) nxge_init_fzc_rx_common(nxgep);
764 
765 	return (status);
766 }
767 
768 nxge_status_t
769 nxge_init_fzc_rx_common(p_nxge_t nxgep)
770 {
771 	npi_handle_t	handle;
772 	npi_status_t	rs = NPI_SUCCESS;
773 	nxge_status_t	status = NXGE_OK;
774 	clock_t		lbolt;
775 	int		table;
776 
777 	nxge_hw_pt_cfg_t *hardware;
778 
779 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rx_common"));
780 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
781 	if (!handle.regp) {
782 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
783 		    "==> nxge_init_fzc_rx_common null ptr"));
784 		return (NXGE_ERROR);
785 	}
786 
787 	/*
788 	 * Configure the rxdma clock divider
789 	 * This is the granularity counter based on
790 	 * the hardware system clock (i.e. 300 Mhz) and
791 	 * it is running around 3 nanoseconds.
792 	 * So, set the clock divider counter to 1000 to get
793 	 * microsecond granularity.
794 	 * For example, for a 3 microsecond timeout, the timeout
795 	 * will be set to 1.
796 	 */
797 	rs = npi_rxdma_cfg_clock_div_set(handle, RXDMA_CK_DIV_DEFAULT);
798 	if (rs != NPI_SUCCESS)
799 		return (NXGE_ERROR | rs);
800 
801 #if defined(__i386)
802 	rs = npi_rxdma_cfg_32bitmode_enable(handle);
803 	if (rs != NPI_SUCCESS)
804 		return (NXGE_ERROR | rs);
805 	rs = npi_txdma_mode32_set(handle, B_TRUE);
806 	if (rs != NPI_SUCCESS)
807 		return (NXGE_ERROR | rs);
808 #endif
809 
810 	/*
811 	 * Enable WRED and program an initial value.
812 	 * Use time to set the initial random number.
813 	 */
814 	(void) drv_getparm(LBOLT, &lbolt);
815 	rs = npi_rxdma_cfg_red_rand_init(handle, (uint16_t)lbolt);
816 	if (rs != NPI_SUCCESS)
817 		return (NXGE_ERROR | rs);
818 
819 	hardware = &nxgep->pt_config.hw_config;
820 	for (table = 0; table < NXGE_MAX_RDC_GRPS; table++) {
821 		/* Does this table belong to <nxgep>? */
822 		if (hardware->grpids[table] == (nxgep->function_num + 256))
823 			status = nxge_init_fzc_rdc_tbl(nxgep, table);
824 	}
825 
826 	/* Ethernet Timeout Counter (?) */
827 
828 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
829 	    "<== nxge_init_fzc_rx_common:status 0x%08x", status));
830 
831 	return (status);
832 }
833 
834 nxge_status_t
835 nxge_init_fzc_rdc_tbl(p_nxge_t nxge, int rdc_tbl)
836 {
837 	nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
838 	nx_rdc_tbl_t	*table;
839 	nxge_rdc_grp_t	*group;
840 	npi_handle_t	handle;
841 
842 	npi_status_t	rs = NPI_SUCCESS;
843 	nxge_status_t	status = NXGE_OK;
844 
845 	NXGE_DEBUG_MSG((nxge, DMA_CTL, "==> nxge_init_fzc_rdc_tbl(%d)", table));
846 
847 	group = &nxge->pt_config.rdc_grps[rdc_tbl];
848 
849 	/* This RDC table must have been previously bound to <nxge>. */
850 	MUTEX_ENTER(&nhd->lock);
851 	table = &nhd->rdc_tbl[rdc_tbl];
852 	if (table->nxge != (uintptr_t)nxge) {
853 		MUTEX_EXIT(&nhd->lock);
854 		NXGE_ERROR_MSG((nxge, DMA_CTL,
855 		    "nxge_init_fzc_rdc_tbl(%d): not owner", table));
856 		return (NXGE_ERROR);
857 	} else {
858 		table->map = group->map;
859 	}
860 	MUTEX_EXIT(&nhd->lock);
861 
862 	handle = NXGE_DEV_NPI_HANDLE(nxge);
863 
864 	rs = npi_rxdma_rdc_table_config(handle, rdc_tbl,
865 	    group->map, group->max_rdcs);
866 
867 	if (rs != NPI_SUCCESS) {
868 		status = NXGE_ERROR | rs;
869 	}
870 
871 	NXGE_DEBUG_MSG((nxge, DMA_CTL, "<== nxge_init_fzc_rdc_tbl(%d)", table));
872 	return (status);
873 }
874 
875 static
876 int
877 rdc_tbl_bind(p_nxge_t nxge, int rdc_tbl)
878 {
879 	nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
880 	nx_rdc_tbl_t *table;
881 	int i;
882 
883 	NXGE_DEBUG_MSG((nxge, DMA_CTL, "==> nxge_fzc_rdc_tbl_bind"));
884 
885 	MUTEX_ENTER(&nhd->lock);
886 	/* is the caller asking for a particular table? */
887 	if (rdc_tbl >= 0 && rdc_tbl < NXGE_MAX_RDC_GROUPS) {
888 		table = &nhd->rdc_tbl[rdc_tbl];
889 		if (table->nxge == 0) {
890 			table->nxge = (uintptr_t)nxge; /* It is now bound. */
891 			NXGE_DEBUG_MSG((nxge, DMA_CTL,
892 			    "<== nxge_fzc_rdc_tbl_bind(%d)", rdc_tbl));
893 			MUTEX_EXIT(&nhd->lock);
894 			return (rdc_tbl);
895 		}
896 	} else {	/* The caller will take any old RDC table. */
897 		for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) {
898 			nx_rdc_tbl_t *table = &nhd->rdc_tbl[i];
899 			if (table->nxge == 0) {
900 				table->nxge = (uintptr_t)nxge;
901 				/* It is now bound. */
902 				MUTEX_EXIT(&nhd->lock);
903 				NXGE_DEBUG_MSG((nxge, DMA_CTL,
904 				    "<== nxge_fzc_rdc_tbl_bind: %d", i));
905 				return (i);
906 			}
907 		}
908 	}
909 	MUTEX_EXIT(&nhd->lock);
910 
911 	NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_fzc_rdc_tbl_bind"));
912 
913 	return (-EBUSY);	/* RDC tables are bound. */
914 }
915 
916 int
917 nxge_fzc_rdc_tbl_bind(
918 	nxge_t *nxge,
919 	int grp_index,
920 	int acceptNoSubstitutes)
921 {
922 	nxge_hw_pt_cfg_t *hardware;
923 	int index;
924 
925 	hardware = &nxge->pt_config.hw_config;
926 
927 	if ((index = rdc_tbl_bind(nxge, grp_index)) < 0) {
928 		if (acceptNoSubstitutes)
929 			return (index);
930 		index = rdc_tbl_bind(nxge, grp_index);
931 		if (index < 0) {
932 			NXGE_ERROR_MSG((nxge, OBP_CTL,
933 			    "nxge_fzc_rdc_tbl_init: "
934 			    "there are no free RDC tables!"));
935 			return (index);
936 		}
937 	}
938 
939 	hardware->grpids[index] = nxge->function_num + 256;
940 
941 	return (index);
942 }
943 
944 int
945 nxge_fzc_rdc_tbl_unbind(p_nxge_t nxge, int rdc_tbl)
946 {
947 	nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
948 	nx_rdc_tbl_t *table;
949 
950 	NXGE_DEBUG_MSG((nxge, DMA_CTL, "==> nxge_fzc_rdc_tbl_unbind(%d)",
951 	    rdc_tbl));
952 
953 	table = &nhd->rdc_tbl[rdc_tbl];
954 	if (table->nxge != (uintptr_t)nxge) {
955 		NXGE_ERROR_MSG((nxge, DMA_CTL,
956 		    "nxge_fzc_rdc_tbl_unbind(%d): func%d not owner",
957 		    nxge->function_num, rdc_tbl));
958 		return (EINVAL);
959 	} else {
960 		bzero(table, sizeof (*table));
961 	}
962 
963 	NXGE_DEBUG_MSG((nxge, DMA_CTL, "<== nxge_fzc_rdc_tbl_unbind(%d)",
964 	    rdc_tbl));
965 
966 	return (0);
967 }
968 
969 nxge_status_t
970 nxge_init_fzc_rxdma_port(p_nxge_t nxgep)
971 {
972 	npi_handle_t		handle;
973 	p_nxge_dma_pt_cfg_t	p_all_cfgp;
974 	p_nxge_hw_pt_cfg_t	p_cfgp;
975 	hostinfo_t 		hostinfo;
976 	int			i;
977 	npi_status_t		rs = NPI_SUCCESS;
978 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
979 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rxdma_port"));
980 
981 	p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
982 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
983 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
984 	/*
985 	 * Initialize the port scheduler DRR weight.
986 	 * npi_rxdma_cfg_port_ddr_weight();
987 	 */
988 
989 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
990 	    (nxgep->mac.portmode == PORT_1G_FIBER) ||
991 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
992 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
993 		rs = npi_rxdma_cfg_port_ddr_weight(handle,
994 		    nxgep->function_num, NXGE_RX_DRR_WT_1G);
995 		if (rs != NPI_SUCCESS) {
996 			return (NXGE_ERROR | rs);
997 		}
998 	}
999 
1000 	/* Program the default RDC of a port */
1001 	rs = npi_rxdma_cfg_default_port_rdc(handle, nxgep->function_num,
1002 	    p_cfgp->def_rdc);
1003 	if (rs != NPI_SUCCESS) {
1004 		return (NXGE_ERROR | rs);
1005 	}
1006 
1007 	/*
1008 	 * Configure the MAC host info table with RDC tables
1009 	 */
1010 	hostinfo.value = 0;
1011 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1012 	for (i = 0; i < p_cfgp->max_macs; i++) {
1013 		hostinfo.bits.w0.rdc_tbl_num = p_cfgp->def_mac_rxdma_grpid;
1014 		hostinfo.bits.w0.mac_pref = p_cfgp->mac_pref;
1015 		if (p_class_cfgp->mac_host_info[i].flag) {
1016 			hostinfo.bits.w0.rdc_tbl_num =
1017 			    p_class_cfgp->mac_host_info[i].rdctbl;
1018 			hostinfo.bits.w0.mac_pref =
1019 			    p_class_cfgp->mac_host_info[i].mpr_npr;
1020 		}
1021 
1022 		rs = npi_mac_hostinfo_entry(handle, OP_SET,
1023 		    nxgep->function_num, i, &hostinfo);
1024 		if (rs != NPI_SUCCESS)
1025 			return (NXGE_ERROR | rs);
1026 	}
1027 
1028 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
1029 	    "<== nxge_init_fzc_rxdma_port rs 0x%08x", rs));
1030 
1031 	return (NXGE_OK);
1032 
1033 }
1034 
1035 nxge_status_t
1036 nxge_fzc_dmc_def_port_rdc(p_nxge_t nxgep, uint8_t port, uint16_t rdc)
1037 {
1038 	npi_status_t rs = NPI_SUCCESS;
1039 	rs = npi_rxdma_cfg_default_port_rdc(nxgep->npi_reg_handle,
1040 	    port, rdc);
1041 	if (rs & NPI_FAILURE)
1042 		return (NXGE_ERROR | rs);
1043 	return (NXGE_OK);
1044 }
1045 
1046 /*
1047  * nxge_init_fzc_tdc_pages
1048  *
1049  *	Configure a TDC's logical pages.
1050  *
1051  *	This function is executed by the service domain, on behalf of
1052  *	a guest domain, to whom this TDC has been loaned.
1053  *
1054  * Arguments:
1055  * 	nxgep
1056  * 	channel		The channel to initialize.
1057  * 	page0		Logical page 0 definition.
1058  * 	page1		Logical page 1 definition.
1059  *
1060  * Notes:
1061  *	I think that this function can be called from any
1062  *	domain, but I need to check.
1063  *
1064  * NPI/NXGE function calls:
1065  *	hv_niu_tx_logical_page_conf()
1066  *	hv_niu_tx_logical_page_info()
1067  *
1068  * Context:
1069  *	Any domain
1070  */
1071 nxge_status_t
1072 nxge_init_fzc_tdc_pages(
1073 	p_nxge_t nxgep,
1074 	uint16_t channel,
1075 	dma_log_page_t *page0,
1076 	dma_log_page_t *page1)
1077 {
1078 	npi_handle_t handle;
1079 	npi_status_t rs;
1080 
1081 	log_page_hdl_t page_handle;
1082 
1083 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
1084 	    "==> nxge_init_fzc_txdma_channel_pages"));
1085 
1086 #ifndef	NIU_HV_WORKAROUND
1087 	if (nxgep->niu_type == N2_NIU) {
1088 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
1089 		    "<== nxge_init_fzc_tdc_pages: "
1090 		    "N2_NIU: no need to set txdma logical pages"));
1091 		return (NXGE_OK);
1092 	}
1093 #else
1094 	if (nxgep->niu_type == N2_NIU) {
1095 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
1096 		    "<== nxge_init_fzc_tdc_pages: "
1097 		    "N2_NIU: NEED to set txdma logical pages"));
1098 	}
1099 #endif
1100 
1101 	/*
1102 	 * Initialize logical page 1.
1103 	 */
1104 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
1105 	if ((rs = npi_txdma_log_page_set(handle, channel, page0))
1106 	    != NPI_SUCCESS)
1107 		return (NXGE_ERROR | rs);
1108 
1109 	/*
1110 	 * Initialize logical page 2.
1111 	 */
1112 	if ((rs = npi_txdma_log_page_set(handle, channel, page1))
1113 	    != NPI_SUCCESS)
1114 		return (NXGE_ERROR | rs);
1115 
1116 	/*
1117 	 * Initialize the page handle.
1118 	 * (In the current driver, this is always set to 0.)
1119 	 */
1120 	page_handle.value = 0;
1121 	rs = npi_txdma_log_page_handle_set(handle, channel, &page_handle);
1122 	if (rs == NPI_SUCCESS) {
1123 		return (NXGE_OK);
1124 	} else {
1125 		return (NXGE_ERROR | rs);
1126 	}
1127 }
1128 
1129 nxge_status_t
1130 nxge_init_fzc_txdma_channel_pages(p_nxge_t nxgep, uint16_t channel,
1131 	p_tx_ring_t tx_ring_p)
1132 {
1133 	npi_handle_t		handle;
1134 	dma_log_page_t		cfg;
1135 	npi_status_t		rs = NPI_SUCCESS;
1136 
1137 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
1138 	    "==> nxge_init_fzc_txdma_channel_pages"));
1139 
1140 #ifndef	NIU_HV_WORKAROUND
1141 	if (nxgep->niu_type == N2_NIU) {
1142 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
1143 		    "<== nxge_init_fzc_txdma_channel_pages: "
1144 		    "N2_NIU: no need to set txdma logical pages"));
1145 		return (NXGE_OK);
1146 	}
1147 #else
1148 	if (nxgep->niu_type == N2_NIU) {
1149 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
1150 		    "<== nxge_init_fzc_txdma_channel_pages: "
1151 		    "N2_NIU: NEED to set txdma logical pages"));
1152 	}
1153 #endif
1154 
1155 	/*
1156 	 * Initialize logical page 1.
1157 	 */
1158 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
1159 	cfg.func_num = nxgep->function_num;
1160 	cfg.page_num = 0;
1161 	cfg.valid = tx_ring_p->page_valid.bits.ldw.page0;
1162 	cfg.value = tx_ring_p->page_value_1.value;
1163 	cfg.mask = tx_ring_p->page_mask_1.value;
1164 	cfg.reloc = tx_ring_p->page_reloc_1.value;
1165 
1166 	rs = npi_txdma_log_page_set(handle, channel,
1167 	    (p_dma_log_page_t)&cfg);
1168 	if (rs != NPI_SUCCESS) {
1169 		return (NXGE_ERROR | rs);
1170 	}
1171 
1172 	/*
1173 	 * Initialize logical page 2.
1174 	 */
1175 	cfg.page_num = 1;
1176 	cfg.valid = tx_ring_p->page_valid.bits.ldw.page1;
1177 	cfg.value = tx_ring_p->page_value_2.value;
1178 	cfg.mask = tx_ring_p->page_mask_2.value;
1179 	cfg.reloc = tx_ring_p->page_reloc_2.value;
1180 
1181 	rs = npi_txdma_log_page_set(handle, channel, &cfg);
1182 	if (rs != NPI_SUCCESS) {
1183 		return (NXGE_ERROR | rs);
1184 	}
1185 
1186 	/* Initialize the page handle */
1187 	rs = npi_txdma_log_page_handle_set(handle, channel,
1188 	    &tx_ring_p->page_hdl);
1189 
1190 	if (rs == NPI_SUCCESS) {
1191 		return (NXGE_OK);
1192 	} else {
1193 		return (NXGE_ERROR | rs);
1194 	}
1195 }
1196 
1197 
1198 nxge_status_t
1199 nxge_init_fzc_txdma_channel_drr(p_nxge_t nxgep, uint16_t channel,
1200 	p_tx_ring_t tx_ring_p)
1201 {
1202 	npi_status_t	rs = NPI_SUCCESS;
1203 	npi_handle_t	handle;
1204 
1205 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
1206 	rs = npi_txc_dma_max_burst_set(handle, channel,
1207 	    tx_ring_p->max_burst.value);
1208 	if (rs == NPI_SUCCESS) {
1209 		return (NXGE_OK);
1210 	} else {
1211 		return (NXGE_ERROR | rs);
1212 	}
1213 }
1214 
1215 nxge_status_t
1216 nxge_fzc_sys_err_mask_set(p_nxge_t nxgep, uint64_t mask)
1217 {
1218 	npi_status_t	rs = NPI_SUCCESS;
1219 	npi_handle_t	handle;
1220 
1221 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
1222 	rs = npi_fzc_sys_err_mask_set(handle, mask);
1223 	if (rs == NPI_SUCCESS) {
1224 		return (NXGE_OK);
1225 	} else {
1226 		return (NXGE_ERROR | rs);
1227 	}
1228 }
1229 
1230 /*
1231  * nxge_init_hv_fzc_txdma_channel_pages
1232  *
1233  *	Configure a TDC's logical pages.
1234  *
1235  * Arguments:
1236  * 	nxgep
1237  * 	channel		The channel to initialize.
1238  * 	tx_ring_p	The transmit ring.
1239  *
1240  * Notes:
1241  *	I think that this function can be called from any
1242  *	domain, but I need to check.
1243  *
1244  * NPI/NXGE function calls:
1245  *	hv_niu_tx_logical_page_conf()
1246  *	hv_niu_tx_logical_page_info()
1247  *
1248  * Context:
1249  *	Any domain
1250  */
1251 #if defined(sun4v) && defined(NIU_LP_WORKAROUND)
1252 nxge_status_t
1253 nxge_init_hv_fzc_txdma_channel_pages(p_nxge_t nxgep, uint16_t channel,
1254 	p_tx_ring_t tx_ring_p)
1255 {
1256 	int			err;
1257 	uint64_t		hverr;
1258 #ifdef	DEBUG
1259 	uint64_t		ra, size;
1260 #endif
1261 
1262 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
1263 	    "==> nxge_init_hv_fzc_txdma_channel_pages"));
1264 
1265 	if (tx_ring_p->hv_set) {
1266 		return (NXGE_OK);
1267 	}
1268 
1269 	/*
1270 	 * Initialize logical page 1 for data buffers.
1271 	 */
1272 	hverr = hv_niu_tx_logical_page_conf((uint64_t)channel,
1273 	    (uint64_t)0,
1274 	    tx_ring_p->hv_tx_buf_base_ioaddr_pp,
1275 	    tx_ring_p->hv_tx_buf_ioaddr_size);
1276 
1277 	err = (nxge_status_t)nxge_herr2kerr(hverr);
1278 	if (err != 0) {
1279 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1280 		    "<== nxge_init_hv_fzc_txdma_channel_pages: channel %d "
1281 		    "error status 0x%x "
1282 		    "(page 0 data buf) hverr 0x%llx "
1283 		    "ioaddr_pp $%p "
1284 		    "size 0x%llx ",
1285 		    channel,
1286 		    err,
1287 		    hverr,
1288 		    tx_ring_p->hv_tx_buf_base_ioaddr_pp,
1289 		    tx_ring_p->hv_tx_buf_ioaddr_size));
1290 		return (NXGE_ERROR | err);
1291 	}
1292 
1293 #ifdef	DEBUG
1294 	ra = size = 0;
1295 	hverr = hv_niu_tx_logical_page_info((uint64_t)channel,
1296 	    (uint64_t)0,
1297 	    &ra,
1298 	    &size);
1299 
1300 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
1301 	    "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d "
1302 	    "ok status 0x%x "
1303 	    "(page 0 data buf) hverr 0x%llx "
1304 	    "set ioaddr_pp $%p "
1305 	    "set size 0x%llx "
1306 	    "get ra ioaddr_pp $%p "
1307 	    "get size 0x%llx ",
1308 	    channel,
1309 	    err,
1310 	    hverr,
1311 	    tx_ring_p->hv_tx_buf_base_ioaddr_pp,
1312 	    tx_ring_p->hv_tx_buf_ioaddr_size,
1313 	    ra,
1314 	    size));
1315 #endif
1316 
1317 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
1318 	    "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d "
1319 	    "(page 0 data buf) hverr 0x%llx "
1320 	    "ioaddr_pp $%p "
1321 	    "size 0x%llx ",
1322 	    channel,
1323 	    hverr,
1324 	    tx_ring_p->hv_tx_buf_base_ioaddr_pp,
1325 	    tx_ring_p->hv_tx_buf_ioaddr_size));
1326 
1327 	/*
1328 	 * Initialize logical page 2 for control buffers.
1329 	 */
1330 	hverr = hv_niu_tx_logical_page_conf((uint64_t)channel,
1331 	    (uint64_t)1,
1332 	    tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
1333 	    tx_ring_p->hv_tx_cntl_ioaddr_size);
1334 
1335 	err = (nxge_status_t)nxge_herr2kerr(hverr);
1336 
1337 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
1338 	    "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d"
1339 	    "ok status 0x%x "
1340 	    "(page 1 cntl buf) hverr 0x%llx "
1341 	    "ioaddr_pp $%p "
1342 	    "size 0x%llx ",
1343 	    channel,
1344 	    err,
1345 	    hverr,
1346 	    tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
1347 	    tx_ring_p->hv_tx_cntl_ioaddr_size));
1348 
1349 	if (err != 0) {
1350 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1351 		    "<== nxge_init_hv_fzc_txdma_channel_pages: channel %d"
1352 		    "error status 0x%x "
1353 		    "(page 1 cntl buf) hverr 0x%llx "
1354 		    "ioaddr_pp $%p "
1355 		    "size 0x%llx ",
1356 		    channel,
1357 		    err,
1358 		    hverr,
1359 		    tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
1360 		    tx_ring_p->hv_tx_cntl_ioaddr_size));
1361 		return (NXGE_ERROR | err);
1362 	}
1363 
1364 #ifdef	DEBUG
1365 	ra = size = 0;
1366 	hverr = hv_niu_tx_logical_page_info((uint64_t)channel,
1367 	    (uint64_t)1,
1368 	    &ra,
1369 	    &size);
1370 
1371 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
1372 	    "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d "
1373 	    "(page 1 cntl buf) hverr 0x%llx "
1374 	    "set ioaddr_pp $%p "
1375 	    "set size 0x%llx "
1376 	    "get ra ioaddr_pp $%p "
1377 	    "get size 0x%llx ",
1378 	    channel,
1379 	    hverr,
1380 	    tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
1381 	    tx_ring_p->hv_tx_cntl_ioaddr_size,
1382 	    ra,
1383 	    size));
1384 #endif
1385 
1386 	tx_ring_p->hv_set = B_TRUE;
1387 
1388 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
1389 	    "<== nxge_init_hv_fzc_txdma_channel_pages"));
1390 
1391 	return (NXGE_OK);
1392 }
1393 
1394 /*ARGSUSED*/
1395 nxge_status_t
1396 nxge_init_hv_fzc_rxdma_channel_pages(p_nxge_t nxgep,
1397 		uint16_t channel, p_rx_rbr_ring_t rbrp)
1398 {
1399 	int			err;
1400 	uint64_t		hverr;
1401 #ifdef	DEBUG
1402 	uint64_t		ra, size;
1403 #endif
1404 
1405 	NXGE_DEBUG_MSG((nxgep, RX_CTL,
1406 	    "==> nxge_init_hv_fzc_rxdma_channel_pages"));
1407 
1408 	if (rbrp->hv_set) {
1409 		return (NXGE_OK);
1410 	}
1411 
1412 	/* Initialize data buffers for page 0 */
1413 	hverr = hv_niu_rx_logical_page_conf((uint64_t)channel,
1414 	    (uint64_t)0,
1415 	    rbrp->hv_rx_buf_base_ioaddr_pp,
1416 	    rbrp->hv_rx_buf_ioaddr_size);
1417 	err = (nxge_status_t)nxge_herr2kerr(hverr);
1418 	if (err != 0) {
1419 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1420 		    "<== nxge_init_hv_fzc_rxdma_channel_pages: channel %d"
1421 		    "error status 0x%x "
1422 		    "(page 0 data buf) hverr 0x%llx "
1423 		    "ioaddr_pp $%p "
1424 		    "size 0x%llx ",
1425 		    channel,
1426 		    err,
1427 		    hverr,
1428 		    rbrp->hv_rx_buf_base_ioaddr_pp,
1429 		    rbrp->hv_rx_buf_ioaddr_size));
1430 
1431 		return (NXGE_ERROR | err);
1432 	}
1433 
1434 #ifdef	DEBUG
1435 	ra = size = 0;
1436 	(void) hv_niu_rx_logical_page_info((uint64_t)channel,
1437 	    (uint64_t)0,
1438 	    &ra,
1439 	    &size);
1440 
1441 	NXGE_DEBUG_MSG((nxgep, RX_CTL,
1442 	    "==> nxge_init_hv_fzc_rxdma_channel_pages: channel %d "
1443 	    "ok status 0x%x "
1444 	    "(page 0 data buf) hverr 0x%llx "
1445 	    "set databuf ioaddr_pp $%p "
1446 	    "set databuf size 0x%llx "
1447 	    "get databuf ra ioaddr_pp %p "
1448 	    "get databuf size 0x%llx",
1449 	    channel,
1450 	    err,
1451 	    hverr,
1452 	    rbrp->hv_rx_buf_base_ioaddr_pp,
1453 	    rbrp->hv_rx_buf_ioaddr_size,
1454 	    ra,
1455 	    size));
1456 #endif
1457 
1458 	/* Initialize control buffers for logical page 1.  */
1459 	hverr = hv_niu_rx_logical_page_conf((uint64_t)channel,
1460 	    (uint64_t)1,
1461 	    rbrp->hv_rx_cntl_base_ioaddr_pp,
1462 	    rbrp->hv_rx_cntl_ioaddr_size);
1463 
1464 	err = (nxge_status_t)nxge_herr2kerr(hverr);
1465 	if (err != 0) {
1466 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1467 		    "<== nxge_init_hv_fzc_rxdma_channel_pages: channel %d"
1468 		    "error status 0x%x "
1469 		    "(page 1 cntl buf) hverr 0x%llx "
1470 		    "ioaddr_pp $%p "
1471 		    "size 0x%llx ",
1472 		    channel,
1473 		    err,
1474 		    hverr,
1475 		    rbrp->hv_rx_buf_base_ioaddr_pp,
1476 		    rbrp->hv_rx_buf_ioaddr_size));
1477 
1478 		return (NXGE_ERROR | err);
1479 	}
1480 
1481 #ifdef	DEBUG
1482 	ra = size = 0;
1483 	(void) hv_niu_rx_logical_page_info((uint64_t)channel,
1484 	    (uint64_t)1,
1485 	    &ra,
1486 	    &size);
1487 
1488 
1489 	NXGE_DEBUG_MSG((nxgep, RX_CTL,
1490 	    "==> nxge_init_hv_fzc_rxdma_channel_pages: channel %d "
1491 	    "error status 0x%x "
1492 	    "(page 1 cntl buf) hverr 0x%llx "
1493 	    "set cntl ioaddr_pp $%p "
1494 	    "set cntl size 0x%llx "
1495 	    "get cntl ioaddr_pp $%p "
1496 	    "get cntl size 0x%llx ",
1497 	    channel,
1498 	    err,
1499 	    hverr,
1500 	    rbrp->hv_rx_cntl_base_ioaddr_pp,
1501 	    rbrp->hv_rx_cntl_ioaddr_size,
1502 	    ra,
1503 	    size));
1504 #endif
1505 
1506 	rbrp->hv_set = B_FALSE;
1507 
1508 	NXGE_DEBUG_MSG((nxgep, RX_CTL,
1509 	    "<== nxge_init_hv_fzc_rxdma_channel_pages"));
1510 
1511 	return (NXGE_OK);
1512 }
1513 
1514 /*
1515  * Map hypervisor error code to errno. Only
1516  * H_ENORADDR, H_EBADALIGN and H_EINVAL are meaningful
1517  * for niu driver. Any other error codes are mapped to EINVAL.
1518  */
1519 static int
1520 nxge_herr2kerr(uint64_t hv_errcode)
1521 {
1522 	int	s_errcode;
1523 
1524 	switch (hv_errcode) {
1525 	case H_ENORADDR:
1526 	case H_EBADALIGN:
1527 		s_errcode = EFAULT;
1528 		break;
1529 	case H_EOK:
1530 		s_errcode = 0;
1531 		break;
1532 	default:
1533 		s_errcode = EINVAL;
1534 		break;
1535 	}
1536 	return (s_errcode);
1537 }
1538 
1539 #endif	/* sun4v and NIU_LP_WORKAROUND */
1540