/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <hxge_impl.h>
#include <hpi_vmac.h>
#include <hpi_rxdma.h>
/*
* System interrupt registers that are under function zero management.
*/
hxge_status_t
hxge_fzc_intr_init(p_hxge_t hxgep)
{
hxge_status_t status = HXGE_OK;
HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_fzc_intr_init"));
/* Configure the initial timer resolution */
if ((status = hxge_fzc_intr_tmres_set(hxgep)) != HXGE_OK) {
return (status);
}
/*
* Set up the logical device group's logical devices that
* the group owns.
*/
if ((status = hxge_fzc_intr_ldg_num_set(hxgep)) != HXGE_OK) {
return (status);
}
/* Configure the system interrupt data */
if ((status = hxge_fzc_intr_sid_set(hxgep)) != HXGE_OK) {
return (status);
}
HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_fzc_intr_init"));
return (status);
}
hxge_status_t
hxge_fzc_intr_ldg_num_set(p_hxge_t hxgep)
{
p_hxge_ldg_t ldgp;
p_hxge_ldv_t ldvp;
hpi_handle_t handle;
int i, j;
hpi_status_t rs = HPI_SUCCESS;
HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_fzc_intr_ldg_num_set"));
if (hxgep->ldgvp == NULL) {
return (HXGE_ERROR);
}
ldgp = hxgep->ldgvp->ldgp;
ldvp = hxgep->ldgvp->ldvp;
if (ldgp == NULL || ldvp == NULL) {
return (HXGE_ERROR);
}
handle = HXGE_DEV_HPI_HANDLE(hxgep);
for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) {
HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_fzc_intr_ldg_num_set "
"<== hxge_f(Hydra): # ldv %d in group %d", ldgp->nldvs,
ldgp->ldg));
for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
rs = hpi_fzc_ldg_num_set(handle, ldvp->ldv,
ldvp->ldg_assigned);
if (rs != HPI_SUCCESS) {
HXGE_DEBUG_MSG((hxgep, INT_CTL,
"<== hxge_fzc_intr_ldg_num_set failed "
" rs 0x%x ldv %d ldg %d",
rs, ldvp->ldv, ldvp->ldg_assigned));
return (HXGE_ERROR | rs);
}
HXGE_DEBUG_MSG((hxgep, INT_CTL,
"<== hxge_fzc_intr_ldg_num_set OK ldv %d ldg %d",
ldvp->ldv, ldvp->ldg_assigned));
}
}
HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_fzc_intr_ldg_num_set"));
return (HXGE_OK);
}
hxge_status_t
hxge_fzc_intr_tmres_set(p_hxge_t hxgep)
{
hpi_handle_t handle;
hpi_status_t rs = HPI_SUCCESS;
HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_fzc_intr_tmrese_set"));
if (hxgep->ldgvp == NULL) {
return (HXGE_ERROR);
}
handle = HXGE_DEV_HPI_HANDLE(hxgep);
if ((rs = hpi_fzc_ldg_timer_res_set(handle, hxgep->ldgvp->tmres))) {
return (HXGE_ERROR | rs);
}
HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_fzc_intr_tmrese_set"));
return (HXGE_OK);
}
hxge_status_t
hxge_fzc_intr_sid_set(p_hxge_t hxgep)
{
hpi_handle_t handle;
p_hxge_ldg_t ldgp;
fzc_sid_t sid;
int i;
hpi_status_t rs = HPI_SUCCESS;
HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_fzc_intr_sid_set"));
if (hxgep->ldgvp == NULL) {
HXGE_DEBUG_MSG((hxgep, INT_CTL,
"<== hxge_fzc_intr_sid_set: no ldg"));
return (HXGE_ERROR);
}
handle = HXGE_DEV_HPI_HANDLE(hxgep);
ldgp = hxgep->ldgvp->ldgp;
HXGE_DEBUG_MSG((hxgep, INT_CTL,
"==> hxge_fzc_intr_sid_set: #int %d", hxgep->ldgvp->ldg_intrs));
for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) {
sid.ldg = ldgp->ldg;
sid.vector = ldgp->vector;
HXGE_DEBUG_MSG((hxgep, INT_CTL,
"==> hxge_fzc_intr_sid_set(%d): group %d vector %d",
i, sid.ldg, sid.vector));
rs = hpi_fzc_sid_set(handle, sid);
if (rs != HPI_SUCCESS) {
HXGE_DEBUG_MSG((hxgep, INT_CTL,
"<== hxge_fzc_intr_sid_set:failed 0x%x", rs));
return (HXGE_ERROR | rs);
}
}
HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_fzc_intr_sid_set"));
return (HXGE_OK);
}
/*
* Receive DMA registers that are under function zero management.
*/
/*ARGSUSED*/
hxge_status_t
hxge_init_fzc_rxdma_channel(p_hxge_t hxgep, uint16_t channel,
p_rx_rbr_ring_t rbr_p, p_rx_rcr_ring_t rcr_p, p_rx_mbox_t mbox_p)
{
hxge_status_t status = HXGE_OK;
HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_init_fzc_rxdma_channel"));
/* Initialize the RXDMA logical pages */
status = hxge_init_fzc_rxdma_channel_pages(hxgep, channel, rbr_p);
if (status != HXGE_OK)
return (status);
HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_init_fzc_rxdma_channel"));
return (status);
}
/*ARGSUSED*/
hxge_status_t
hxge_init_fzc_rxdma_channel_pages(p_hxge_t hxgep,
uint16_t channel, p_rx_rbr_ring_t rbrp)
{
hpi_handle_t handle;
hpi_status_t rs = HPI_SUCCESS;
HXGE_DEBUG_MSG((hxgep, DMA_CTL,
"==> hxge_init_fzc_rxdma_channel_pages"));
handle = HXGE_DEV_HPI_HANDLE(hxgep);
/* Initialize the page handle */
rs = hpi_rxdma_cfg_logical_page_handle(handle, channel,
rbrp->page_hdl.bits.handle);
if (rs != HPI_SUCCESS)
return (HXGE_ERROR | rs);
HXGE_DEBUG_MSG((hxgep, DMA_CTL,
"<== hxge_init_fzc_rxdma_channel_pages"));
return (HXGE_OK);
}
/*ARGSUSED*/
hxge_status_t
hxge_init_fzc_txdma_channel(p_hxge_t hxgep, uint16_t channel,
p_tx_ring_t tx_ring_p, p_tx_mbox_t mbox_p)
{
hxge_status_t status = HXGE_OK;
HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_init_fzc_txdma_channel"));
/* Initialize the TXDMA logical pages */
(void) hxge_init_fzc_txdma_channel_pages(hxgep, channel, tx_ring_p);
HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_init_fzc_txdma_channel"));
return (status);
}
hxge_status_t
hxge_init_fzc_rx_common(p_hxge_t hxgep)
{
hpi_handle_t handle;
hpi_status_t rs = HPI_SUCCESS;
hxge_status_t status = HXGE_OK;
HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_init_fzc_rx_common"));
handle = HXGE_DEV_HPI_HANDLE(hxgep);
/*
* Configure the rxdma clock divider
* This is the granularity counter based on
* the hardware system clock (i.e. 300 Mhz) and
* it is running around 3 nanoseconds.
* So, set the clock divider counter to 1000 to get
* microsecond granularity.
* For example, for a 3 microsecond timeout, the timeout
* will be set to 1.
*/
rs = hpi_rxdma_cfg_clock_div_set(handle, RXDMA_CK_DIV_DEFAULT);
if (rs != HPI_SUCCESS)
return (HXGE_ERROR | rs);
HXGE_DEBUG_MSG((hxgep, DMA_CTL,
"<== hxge_init_fzc_rx_common:status 0x%08x", status));
return (status);
}
hxge_status_t
hxge_init_fzc_txdma_channel_pages(p_hxge_t hxgep, uint16_t channel,
p_tx_ring_t tx_ring_p)
{
hpi_handle_t handle;
hpi_status_t rs = HPI_SUCCESS;
HXGE_DEBUG_MSG((hxgep, DMA_CTL,
"==> hxge_init_fzc_txdma_channel_pages"));
handle = HXGE_DEV_HPI_HANDLE(hxgep);
/* Initialize the page handle */
rs = hpi_txdma_log_page_handle_set(handle, channel,
&tx_ring_p->page_hdl);
if (rs == HPI_SUCCESS)
return (HXGE_OK);
else
return (HXGE_ERROR | rs);
}
hxge_status_t
hxge_fzc_sys_err_mask_set(p_hxge_t hxgep, boolean_t mask)
{
hpi_status_t rs = HPI_SUCCESS;
hpi_handle_t handle;
handle = HXGE_DEV_HPI_HANDLE(hxgep);
rs = hpi_fzc_sys_err_mask_set(handle, mask);
if (rs == HPI_SUCCESS)
return (HXGE_OK);
else
return (HXGE_ERROR | rs);
}