/*
* 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 <hpi_vir.h>
#include <hxge_defs.h>
#include <hxge_impl.h>
/*
* Set up a logical group number that a logical device belongs to.
*/
hpi_status_t
hpi_fzc_ldg_num_set(hpi_handle_t handle, uint8_t ld, uint8_t ldg)
{
ld_grp_ctrl_t gnum;
if (!LD_VALID(ld)) {
HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
" hpi_fzc_ldg_num_set ld <0x%x>", ld));
return (HPI_FAILURE | HPI_VIR_LD_INVALID(ld));
}
if (!LDG_VALID(ldg)) {
HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
" hpi_fzc_ldg_num_set ldg <0x%x>", ldg));
return (HPI_FAILURE | HPI_VIR_LDG_INVALID(ld));
}
gnum.value = 0;
gnum.bits.num = ldg;
HXGE_REG_WR32(handle, LD_GRP_CTRL + LD_NUM_OFFSET(ld), gnum.value);
return (HPI_SUCCESS);
}
/*
* Get device state vectors.
*/
hpi_status_t
hpi_ldsv_ldfs_get(hpi_handle_t handle, uint8_t ldg, uint32_t *vector0_p,
uint32_t *vector1_p)
{
int status;
if ((status = hpi_ldsv_get(handle, ldg, VECTOR0, vector0_p))) {
return (status);
}
if ((status = hpi_ldsv_get(handle, ldg, VECTOR1, vector1_p))) {
return (status);
}
return (HPI_SUCCESS);
}
/*
* Get device state vectors.
*/
hpi_status_t
hpi_ldsv_get(hpi_handle_t handle, uint8_t ldg, ldsv_type_t vector,
uint32_t *ldf_p)
{
uint32_t offset;
if (!LDG_VALID(ldg)) {
HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
" hpi_ldsv_get Invalid Input ldg <0x%x>", ldg));
return (HPI_FAILURE | HPI_VIR_LDG_INVALID(ldg));
}
switch (vector) {
case VECTOR0:
offset = LDSV0 + LDSV_OFFSET(ldg);
break;
case VECTOR1:
offset = LDSV1 + LDSV_OFFSET(ldg);
break;
default:
HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
" hpi_ldsv_get Invalid Input: ldsv type <0x%x>", vector));
return (HPI_FAILURE | HPI_VIR_LDSV_INVALID(vector));
}
HXGE_REG_RD32(handle, offset, ldf_p);
return (HPI_SUCCESS);
}
/*
* Set the mask bits for both ldf0 and ldf1.
*/
hpi_status_t
hpi_intr_mask_set(hpi_handle_t handle, uint8_t ld, uint8_t ldf_mask)
{
uint32_t offset;
if (!LD_VALID(ld)) {
HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
" hpi_intr_mask_set ld", ld));
return (HPI_FAILURE | HPI_VIR_LD_INVALID(ld));
}
ldf_mask &= LD_IM_MASK;
offset = LDSV_OFFSET_MASK(ld);
HPI_DEBUG_MSG((handle.function, HPI_VIR_CTL,
"hpi_intr_mask_set: ld %d offset 0x%0x mask 0x%x",
ld, offset, ldf_mask));
HXGE_REG_WR32(handle, offset, (uint32_t)ldf_mask);
return (HPI_SUCCESS);
}
/*
* Set interrupt timer and arm bit.
*/
hpi_status_t
hpi_intr_ldg_mgmt_set(hpi_handle_t handle, uint8_t ldg, boolean_t arm,
uint8_t timer)
{
ld_intr_mgmt_t mgm;
if (!LDG_VALID(ldg)) {
HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
" hpi_intr_ldg_mgmt_set Invalid Input: ldg <0x%x>", ldg));
return (HPI_FAILURE | HPI_VIR_LDG_INVALID(ldg));
}
if (!LD_INTTIMER_VALID(timer)) {
HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
" hpi_intr_ldg_mgmt_set Invalid Input"
" timer <0x%x>", timer));
return (HPI_FAILURE | HPI_VIR_INTM_TM_INVALID(ldg));
}
if (arm) {
mgm.bits.arm = 1;
} else {
HXGE_REG_RD32(handle, LD_INTR_MGMT + LDSV_OFFSET(ldg),
&mgm.value);
}
mgm.bits.timer = timer;
HXGE_REG_WR32(handle, LD_INTR_MGMT + LDSV_OFFSET(ldg), mgm.value);
HPI_DEBUG_MSG((handle.function, HPI_VIR_CTL,
" hpi_intr_ldg_mgmt_set: ldg %d reg offset 0x%x",
ldg, LD_INTR_MGMT + LDSV_OFFSET(ldg)));
return (HPI_SUCCESS);
}
/*
* Set the timer resolution.
*/
hpi_status_t
hpi_fzc_ldg_timer_res_set(hpi_handle_t handle, uint32_t res)
{
ld_intr_tim_res_t tm;
if (res > LDGTITMRES_RES_MASK) {
HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
" hpi_fzc_ldg_timer_res_set Invalid Input: res <0x%x>",
res));
return (HPI_FAILURE | HPI_VIR_TM_RES_INVALID);
}
tm.value = 0;
tm.bits.res = res;
HXGE_REG_WR32(handle, LD_INTR_TIM_RES, tm.value);
return (HPI_SUCCESS);
}
/*
* Set the system interrupt data.
*/
hpi_status_t
hpi_fzc_sid_set(hpi_handle_t handle, fzc_sid_t sid)
{
sid_t sd;
if (!LDG_VALID(sid.ldg)) {
HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
" hpi_fzc_sid_set Invalid Input: ldg <0x%x>", sid.ldg));
return (HPI_FAILURE | HPI_VIR_LDG_INVALID(sid.ldg));
}
if (!SID_VECTOR_VALID(sid.vector)) {
HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
" hpi_fzc_sid_set Invalid Input: vector <0x%x>",
sid.vector));
return (HPI_FAILURE | HPI_VIR_SID_VEC_INVALID(sid.vector));
}
sd.value = 0;
sd.bits.data = sid.vector;
HXGE_REG_WR32(handle, SID + LDG_SID_OFFSET(sid.ldg), sd.value);
return (HPI_SUCCESS);
}
/*
* Mask/Unmask the device error mask bits.
*/
hpi_status_t
hpi_fzc_sys_err_mask_set(hpi_handle_t handle, boolean_t mask)
{
dev_err_mask_t dev_mask;
dev_mask.value = 0;
if (mask) {
dev_mask.bits.tdc_mask0 = 1;
dev_mask.bits.rdc_mask0 = 1;
dev_mask.bits.vnm_pio_mask1 = 1;
dev_mask.bits.tdc_mask1 = 1;
dev_mask.bits.rdc_mask1 = 1;
dev_mask.bits.peu_mask1 = 1;
}
HXGE_REG_WR32(handle, DEV_ERR_MASK, dev_mask.value);
return (HPI_SUCCESS);
}
/*
* Get the system error stats.
*/
hpi_status_t
hpi_fzc_sys_err_stat_get(hpi_handle_t handle, dev_err_stat_t *statp)
{
HXGE_REG_RD32(handle, DEV_ERR_STAT, &statp->value);
return (HPI_SUCCESS);
}