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