#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
#include "n2piupc_acc.h"
#include "n2piupc_tables.h"
#include "n2piupc.h"
#include "n2piupc_biterr.h"
#define REAL_BE2_8_10_MASK 0x3full
typedef struct {
uint64_t sw_biterr_events;
} n2piupc_sw_biterr_t;
int
n2piupc_biterr_attach(void **arg)
{
*arg = kmem_zalloc(sizeof (n2piupc_sw_biterr_t), KM_SLEEP);
return (DDI_SUCCESS);
}
void
n2piupc_biterr_detach(void *arg)
{
if (arg != NULL)
kmem_free(arg, sizeof (n2piupc_sw_biterr_t));
}
int
n2piupc_biterr_write(n2piupc_t *n2piupc_p, int regid, uint64_t data_in)
{
uint64_t dev_data;
cntr_handle_t handle = n2piupc_p->n2piupc_handle;
n2piupc_sw_biterr_t *biterr_p = n2piupc_p->n2piupc_biterr_p;
int rval = SUCCESS;
switch (regid) {
case SW_N2PIU_BITERR_SEL:
dev_data = data_in & BTERR_CTR_ENABLE;
break;
case SW_N2PIU_BITERR_CLR:
dev_data = (biterr_p->sw_biterr_events & BTERR_CTR_ENABLE) |
(data_in & BTERR_CTR_CLR);
break;
default:
N2PIUPC_DBG1("n2piupc_biterr_write: regid %d is invalid\n",
regid);
return (EIO);
}
if (n2piupc_set_perfreg(handle, HVIO_N2PIU_PERFREG_BITERR_CNT1,
dev_data) != H_EOK) {
rval = EIO;
} else if (regid == SW_N2PIU_BITERR_SEL) {
N2PIUPC_DBG1(
"n2piupc_biterr_write: Saving 0x%lx to bterr_sel, "
"write 0x%lx to dev\n", data_in, dev_data);
biterr_p->sw_biterr_events = data_in;
}
N2PIUPC_DBG2("n2piupc_biterr_write: eventsreg:0x%lx, status:%d\n",
biterr_p->sw_biterr_events, rval);
return (rval);
}
int
n2piupc_biterr_read(n2piupc_t *n2piupc_p, int regid, uint64_t *data)
{
uint64_t raw_data;
uint64_t biterr_cnt2_events;
n2piupc_sw_biterr_t *biterr_p = n2piupc_p->n2piupc_biterr_p;
cntr_handle_t handle = n2piupc_p->n2piupc_handle;
int rval = SUCCESS;
N2PIUPC_DBG1("n2piupc_biterr_read enter: handle:0x%lx, regid:%d\n",
handle, regid);
switch (regid) {
case SW_N2PIU_BITERR_CNT1_DATA:
if (n2piupc_get_perfreg(handle, HVIO_N2PIU_PERFREG_BITERR_CNT1,
&raw_data) != H_EOK) {
rval = EIO;
}
break;
case SW_N2PIU_BITERR_CNT2_DATA:
biterr_cnt2_events = biterr_p->sw_biterr_events &
(BTERR_CTR_3_EVT_MASK << BTERR_CTR_3_EVT_OFF);
N2PIUPC_DBG1("n2piupc_biterr_read: counter2 data, evt:%ld\n",
biterr_cnt2_events);
if (biterr_cnt2_events == BTERR3_EVT_ENC_NONE) {
*data = 0ull;
break;
}
if (n2piupc_get_perfreg(handle, HVIO_N2PIU_PERFREG_BITERR_CNT2,
&raw_data) != H_EOK) {
rval = EIO;
break;
}
N2PIUPC_DBG1("n2piupc_read: n2piupc_get_perfreg: data:0x%lx\n",
raw_data);
switch (biterr_cnt2_events) {
case BTERR3_EVT_ENC_ALL:
*data = raw_data;
break;
case BTERR3_EVT_ENC_LANE_0:
case BTERR3_EVT_ENC_LANE_1:
case BTERR3_EVT_ENC_LANE_2:
case BTERR3_EVT_ENC_LANE_3:
case BTERR3_EVT_ENC_LANE_4:
case BTERR3_EVT_ENC_LANE_5:
case BTERR3_EVT_ENC_LANE_6:
case BTERR3_EVT_ENC_LANE_7:
*data = raw_data >>
((biterr_cnt2_events - BTERR3_EVT_ENC_LANE_0) * 8) &
REAL_BE2_8_10_MASK;
N2PIUPC_DBG2(
"DATA: raw:0x%lx, >> (%ld * 8) & 0x%llx = 0x%lx\n",
raw_data,
(biterr_cnt2_events - BTERR3_EVT_ENC_LANE_0),
REAL_BE2_8_10_MASK, *data);
break;
default:
cmn_err(CE_WARN,
"n2piupc: Invalid bterr PIC3 event: 0x%lx\n",
biterr_cnt2_events);
rval = EINVAL;
break;
}
break;
case SW_N2PIU_BITERR_SEL:
N2PIUPC_DBG2("n2piupc_biterr_read: returning events: 0x%lx\n",
biterr_p->sw_biterr_events);
*data = biterr_p->sw_biterr_events;
break;
default:
N2PIUPC_DBG1("n2piupc_biterr_read: invalid regid: %d\n", regid);
rval = EIO;
break;
}
N2PIUPC_DBG1("n2piupc_read exit: data:0x%lx, status:%d\n", *data,
rval);
return (rval);
}