#include "bnxtmr.h"
#include "bnxrcv.h"
#include "bnxgld.h"
#define BNX_LINK_CHECK_INTERVAL 10
#define BNX_LINK_CHECK_INTERVAL2 7
#define BNX_TIMER_INTERVAL 500000
typedef struct _bnx_fw_t {
u32_t shmemaddr;
u32_t length;
u32_t nvramaddr;
} bnx_fw_t;
static void
bnx_link_check(lm_device_t *const lmdevice)
{
if (lmdevice->vars.link_status == LM_STATUS_LINK_ACTIVE) {
if (lmdevice->vars.serdes_fallback_status) {
u32_t intr_exp_status;
(void) lm_mwrite(lmdevice, lmdevice->params.phy_addr,
0x17, 0x0f01);
(void) lm_mread(lmdevice, lmdevice->params.phy_addr,
0x15, &intr_exp_status);
(void) lm_mread(lmdevice, lmdevice->params.phy_addr,
0x15, &intr_exp_status);
if (intr_exp_status & 0x20) {
(void) lm_mwrite(lmdevice,
lmdevice->params.phy_addr,
PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
PHY_CTRL_RESTART_AUTO_NEG);
}
}
} else {
lm_service_phy_int(lmdevice, TRUE);
}
}
static void
bnx_link_check2(lm_device_t *const lmdevice)
{
if (lmdevice->vars.link_status == LM_STATUS_LINK_ACTIVE) {
u32_t val;
u32_t phy_addr;
phy_addr = lmdevice->params.phy_addr;
(void) lm_mwrite(lmdevice, phy_addr, 0x1c, 0x6800);
(void) lm_mread(lmdevice, phy_addr, 0x1c, &val);
(void) lm_mread(lmdevice, phy_addr, 0x1c, &val);
if (val & 2) {
(void) lm_mwrite(lmdevice, phy_addr, 0x17, 0x0f03);
(void) lm_mread(lmdevice, phy_addr, 0x15, &val);
(void) lm_mwrite(lmdevice, phy_addr, 0x15,
val & 0xff0f);
lmdevice->vars.bcm5706s_tx_drv_cur = (u16_t)val;
}
}
}
static void
bnx_timer(void *arg)
{
lm_device_t *lmdevice;
um_device_t *umdevice;
umdevice = (um_device_t *)arg;
lmdevice = &(umdevice->lm_dev);
mutex_enter(&umdevice->tmr_mutex);
if (umdevice->timer_enabled != B_TRUE) {
goto done;
}
um_send_driver_pulse(umdevice);
if (mutex_tryenter(&umdevice->os_param.rcv_mutex)) {
bnx_rxpkts_post(umdevice);
mutex_exit(&umdevice->os_param.rcv_mutex);
}
if (umdevice->timer_link_check_interval2) {
if (umdevice->timer_link_check_interval) {
if (umdevice->timer_link_check_counter) {
if (umdevice->timer_link_check_counter == 1) {
mutex_enter(
&umdevice->os_param.phy_mutex);
bnx_link_check(lmdevice);
mutex_exit(
&umdevice->os_param.phy_mutex);
}
umdevice->timer_link_check_counter--;
}
}
umdevice->timer_link_check_counter2--;
if (umdevice->timer_link_check_counter2 == 0) {
mutex_enter(&umdevice->os_param.phy_mutex);
bnx_link_check2(lmdevice);
mutex_exit(&umdevice->os_param.phy_mutex);
umdevice->timer_link_check_counter2 =
umdevice->timer_link_check_interval2;
}
}
FLUSHPOSTEDWRITES(lmdevice);
umdevice->tmrtid = timeout(bnx_timer, (void *)umdevice,
drv_usectohz(BNX_TIMER_INTERVAL));
done:
mutex_exit(&umdevice->tmr_mutex);
}
void
bnx_timer_start(um_device_t *const umdevice)
{
lm_device_t *lmdevice;
lmdevice = &(umdevice->lm_dev);
umdevice->timer_enabled = B_TRUE;
if (CHIP_NUM(lmdevice) == CHIP_NUM_5706 &&
umdevice->dev_var.isfiber == B_TRUE) {
if (lmdevice->vars.serdes_fallback_select !=
SERDES_FALLBACK_NONE) {
umdevice->timer_link_check_interval =
BNX_LINK_CHECK_INTERVAL;
} else {
umdevice->timer_link_check_interval = 0;
}
umdevice->timer_link_check_interval2 = BNX_LINK_CHECK_INTERVAL2;
umdevice->timer_link_check_counter2 =
umdevice->timer_link_check_interval2;
} else {
umdevice->timer_link_check_interval2 = 0;
}
umdevice->tmrtid = timeout(bnx_timer, (void *)umdevice,
drv_usectohz(BNX_TIMER_INTERVAL));
}
void
bnx_timer_stop(um_device_t *const umdevice)
{
mutex_enter(&umdevice->tmr_mutex);
umdevice->timer_enabled = B_FALSE;
mutex_exit(&umdevice->tmr_mutex);
(void) untimeout(umdevice->tmrtid);
umdevice->tmrtid = 0;
}
void
bnx_link_timer_restart(um_device_t *const umdevice)
{
umdevice->timer_link_check_counter =
umdevice->timer_link_check_interval;
}
void
bnx_timer_init(um_device_t *const umdevice)
{
mutex_init(&umdevice->tmr_mutex, NULL, MUTEX_DRIVER,
DDI_INTR_PRI(umdevice->intrPriority));
}
void
bnx_timer_fini(um_device_t *const umdevice)
{
mutex_destroy(&umdevice->tmr_mutex);
}