#ifndef LIP_PHY_H_
#define LIP_PHY_H_

/***************************************************************************//**
 @addtogroup lip_phy
 @{
 @file lip_phy.h
 @brief Файл содержит определения функций для работы с микросхемой физического уровня.

 В случае использования штатного для порта подключения PHY явный вызов этих
 функций не требуется, т.к. выполняется самим стеком.

 Явный вызов этих функций позволяет реализовать нестандартное подключение PHY,
 вручную создав контекст работы с PHY и вызввая нижеприведенные функции.

 @author Borisov Alexey <borisov@lcard.ru>
******************************************************************************/

#include "lip_phy_mdio.h"
#include "lip_phy_mdio_frame.h"
#include "lip_phy_defs.h"



/** @brief Инициализация интерфейса взаимодействия с PHY. */
t_lip_errs lip_phy_ctx_init(t_lip_phy_ctx *ctx, const t_lip_phy_iface_descr *iface_descr, void *user_ptr);
/** @brief Задание параметров конфигурации PHY. */
t_lip_errs lip_phy_set_cfg(t_lip_phy_ctx *ctx, const t_lip_phy_cfg *cfg);
/** @brief Выполнение фоновых задач по обмену с PHY */
t_lip_errs lip_phy_pull(t_lip_phy_ctx *phy_ctx);
/** @brief Завершение работы с PHY. */
void lip_phy_close(t_lip_phy_ctx *phy_ctx);
/** @brief Программный сброс PHY. */
t_lip_errs lip_phy_sw_reset(t_lip_phy_ctx *phy_ctx, unsigned int tout);

/** @brief Обнаружение подключенной микросхемы PHY */
t_lip_errs lip_phy_detect(t_lip_phy_ctx *phy_ctx);
/** @brief Запись настроек PHY в соответствии с заданной в контексте конфигурацией */
t_lip_errs lip_phy_configure(t_lip_phy_ctx *phy_ctx);
/** @brief Проверка состояния подключения PHY (link up) */
t_lip_errs lip_phy_check_link(t_lip_phy_ctx *phy_ctx);
/** @brief Запрос на проверку состояния подключения PHY (link up) */
t_lip_errs lip_phy_check_link_req(t_lip_phy_ctx *phy_ctx);
/** @brief Обновление информации о текущем режиме работы PHY */
t_lip_errs lip_phy_update_mode(t_lip_phy_ctx *phy_ctx);
/** @brief Чтение флагов возникших прерываний PHY со сбросом */
t_lip_errs lip_phy_rd_intflags(t_lip_phy_ctx *phy_ctx, uint32_t *intflags);

#if LIP_PHY_USE_CABLE_TEST
t_lip_errs lip_phy_cable_test_start(t_lip_phy_ctx *phy_ctx, uint32_t pair_mask);
const t_lip_phy_cable_test_result *lip_phy_cable_test_results(t_lip_phy_ctx *phy_ctx);
#endif

static inline bool lip_phy_link_is_up(const t_lip_phy_ctx *phy_ctx) {
    return phy_ctx->state.flags & LIP_PHY_STATE_FLAG_LINK_UP;
}
static inline bool lip_phy_is_configured(const t_lip_phy_ctx *phy_ctx) {
    return phy_ctx->state.flags & LIP_PHY_STATE_FLAG_WORK_CFG;
}
static inline t_lip_phy_speed lip_phy_cur_speed(t_lip_phy_ctx *phy_ctx) {
    return (t_lip_phy_speed)phy_ctx->state.mode.speed;
}

static inline int lip_phy_speed_mbit(t_lip_phy_speed speed) {
    return speed == LIP_PHY_SPEED_1000 ? 1000 :
           speed == LIP_PHY_SPEED_100  ? 100 :
           speed == LIP_PHY_SPEED_10   ? 10 : 0;
}

#if LIP_PHY_USE_STATS
static inline const t_lip_phy_stats_results *lip_phy_stats_results(const t_lip_phy_ctx *phy_ctx) {
    return &phy_ctx->stats.results;
}
#endif



#endif

