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