/** ****************************************************************************** * * @file ipc_host.h * * @brief IPC module. * * Copyright (C) ESWIN 2015-2020 * ****************************************************************************** */ #ifndef _IPC_HOST_H_ #define _IPC_HOST_H_ /* * INCLUDE FILES ****************************************************************************** */ #include "ipc_shared.h" #ifndef __KERNEL__ #include "arch.h" #else #include "ipc_compat.h" #endif /* * ENUMERATION ****************************************************************************** */ enum ipc_host_desc_status { /// Descriptor is IDLE IPC_HOST_DESC_IDLE = 0, /// Data can be forwarded IPC_HOST_DESC_FORWARD, /// Data has to be kept in UMAC memory IPC_HOST_DESC_KEEP, /// Delete stored packet IPC_HOST_DESC_DELETE, /// Update Frame Length status IPC_HOST_DESC_LEN_UPDATE, }; /** ****************************************************************************** * @brief This structure is used to initialize the MAC SW * * The WLAN device driver provides functions call-back with this structure ****************************************************************************** */ struct ipc_host_cb_tag { /// WLAN driver call-back function: send_data_cfm int (*send_data_cfm)(void *pthis, void *host_id); /// WLAN driver call-back function: handle_data_cfm int (*handle_data_cfm)(void *pthis, void *host_id); /// WLAN driver call-back function: recv_data_ind uint8_t (*recv_data_ind)(void *pthis, void *host_id); /// WLAN driver call-back function: recv_radar_ind uint8_t (*recv_radar_ind)(void *pthis, void *host_id); /// WLAN driver call-back function: recv_unsup_rx_vec_ind uint8_t (*recv_unsup_rx_vec_ind)(void *pthis, void *host_id); /// WLAN driver call-back function: recv_msg_ind uint8_t (*recv_msg_ind)(void *pthis, void *host_id); /// WLAN driver call-back function: recv_msgack_ind uint8_t (*recv_msgack_ind)(void *pthis, void *host_id); /// WLAN driver call-back function: recv_dbg_ind uint8_t (*recv_dbg_ind)(void *pthis, void *host_id); /// WLAN driver call-back function: prim_tbtt_ind void (*prim_tbtt_ind)(void *pthis); /// WLAN driver call-back function: sec_tbtt_ind void (*sec_tbtt_ind)(void *pthis); }; /* * Struct used to store information about host buffers (DMA Address and local pointer) */ struct ipc_hostbuf { void *hostid; ///< ptr to hostbuf client (ipc_host client) structure uint64_t dma_addr; ///< ptr to real hostbuf dma address }; /// Definition of the IPC Host environment structure. struct ipc_host_env_tag { /// Structure containing the callback pointers struct ipc_host_cb_tag cb; /// Pointer to the shared environment struct ipc_shared_env_tag *shared; #ifdef CONFIG_ECRNX_FULLMAC // Array used to store the descriptor addresses struct ipc_hostbuf ipc_host_rxdesc_array[IPC_RXDESC_CNT]; // Index of the host RX descriptor array (ipc_shared environment) uint8_t ipc_host_rxdesc_idx; /// Store the number of RX Descriptors uint8_t rxdesc_nb; #endif //(CONFIG_ECRNX_FULLMAC) /// Fields for Data Rx handling #ifdef CONFIG_ECRNX_SOFTMAC // Global array used to store the hostid and hostbuf addresses struct ipc_hostbuf ipc_host_rxbuf_array[IPC_RXBUF_CNT]; #endif // CONFIG_ECRNX_SOFTMAC // Index used for ipc_host_rxbuf_array to point to current buffer uint8_t ipc_host_rxbuf_idx; // Store the number of Rx Data buffers uint32_t rx_bufnb; // Store the size of the Rx Data buffers uint32_t rx_bufsz; /// Fields for Radar events handling // Global array used to store the hostid and hostbuf addresses struct ipc_hostbuf ipc_host_radarbuf_array[IPC_RADARBUF_CNT]; // Index used for ipc_host_rxbuf_array to point to current buffer uint8_t ipc_host_radarbuf_idx; // Store the number of radar event buffers uint32_t radar_bufnb; // Store the size of the radar event buffers uint32_t radar_bufsz; ///Fields for Unsupported frame handling // Global array used to store the hostid and hostbuf addresses struct ipc_hostbuf ipc_host_unsuprxvecbuf_array[IPC_UNSUPRXVECBUF_CNT]; // Index used for ipc_host_unsuprxvecbuf_array to point to current buffer uint8_t ipc_host_unsuprxvecbuf_idx; // Store the number of unsupported rx vector buffers uint32_t unsuprxvec_bufnb; // Store the size of unsupported rx vector buffers uint32_t unsuprxvec_bufsz; // Index used that points to the first free TX desc uint32_t txdesc_free_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; // Index used that points to the first used TX desc uint32_t txdesc_used_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; // Array storing the currently pushed host ids for the BK queue void *tx_host_id0[CONFIG_USER_MAX][NX_TXDESC_CNT0]; // Array storing the currently pushed host ids for the BE queue void *tx_host_id1[CONFIG_USER_MAX][NX_TXDESC_CNT1]; // Array storing the currently pushed host ids for the VI queue void *tx_host_id2[CONFIG_USER_MAX][NX_TXDESC_CNT2]; // Array storing the currently pushed host ids for the VO queue void *tx_host_id3[CONFIG_USER_MAX][NX_TXDESC_CNT3]; #if NX_TXQ_CNT == 5 // Array storing the currently pushed host ids for the BCN queue void *tx_host_id4[1][NX_TXDESC_CNT4]; #endif // Pointer to the different host ids arrays, per IPC queue void **tx_host_id[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; // Pointer to the different TX descriptor arrays, per IPC queue volatile struct txdesc_host *txdesc[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; /// Fields for Emb->App MSGs handling // Global array used to store the hostid and hostbuf addresses for msg/ind struct ipc_hostbuf ipc_host_msgbuf_array[IPC_MSGE2A_BUF_CNT]; // Index of the MSG E2A buffers array to point to current buffer uint8_t ipc_host_msge2a_idx; // Store the number of E2A MSG buffers uint32_t ipc_e2amsg_bufnb; // Store the size of the E2A MSG buffers uint32_t ipc_e2amsg_bufsz; /// E2A ACKs of A2E MSGs uint8_t msga2e_cnt; void *msga2e_hostid; /// Fields for Debug MSGs handling // Global array used to store the hostid and hostbuf addresses for Debug messages struct ipc_hostbuf ipc_host_dbgbuf_array[IPC_DBGBUF_CNT]; // Index of the Debug messages buffers array to point to current buffer uint8_t ipc_host_dbg_idx; // Store the number of Debug messages buffers uint32_t ipc_dbg_bufnb; // Store the size of the Debug messages buffers uint32_t ipc_dbg_bufsz; /// Pointer to the attached object (used in callbacks and register accesses) void *pthis; }; extern const int nx_txdesc_cnt[]; extern const int nx_txuser_cnt[]; /** ****************************************************************************** * @brief Returns the full/not full status of the queue the index of which is * passed as parameter. * * @param[in] env Pointer to the IPC host environment * @param[in] queue_idx Index of the queue to be checked * * @return true if the queue is full, false otherwise * ****************************************************************************** */ __INLINE bool ipc_host_queue_full(struct ipc_host_env_tag *env, const int queue_idx) { return (env->txdesc_free_idx[queue_idx] == (env->txdesc_used_idx[queue_idx] + nx_txdesc_cnt[queue_idx])); } /** ****************************************************************************** * @brief Initialize the IPC running on the Application CPU. * * This function: * - initializes the IPC software environments * - enables the interrupts in the IPC block * * @param[in] env Pointer to the IPC host environment * * @warning Since this function resets the IPC Shared memory, it must be called * before the LMAC FW is launched because LMAC sets some init values in IPC * Shared memory at boot. * ****************************************************************************** */ void ipc_host_init(struct ipc_host_env_tag *env, struct ipc_host_cb_tag *cb, struct ipc_shared_env_tag *shared_env_ptr, void *pthis); /** @addtogroup IPC_TX * @{ */ /** ****************************************************************************** * @brief Retrieve a new free Tx descriptor (host side). * * This function returns a pointer to the next Tx descriptor available from the * queue queue_idx to the host driver. The driver will have to fill it with the * appropriate endianness and to send it to the * emb side with ipc_host_txdesc_push(). * * This function should only be called once until ipc_host_txdesc_push() is called. * * This function will return NULL if the queue is full. * * @param[in] env Pointer to the IPC host environment * @param[in] queue_idx Queue index. The index can be inferred from the * user priority of the incoming packet. * @param[in] user_pos User position. If MU-MIMO is not used, this value * shall be 0. * @return Pointer to the next Tx descriptor free. This can * point to the host memory or to shared memory, * depending on IPC implementation. * ****************************************************************************** */ volatile struct txdesc_host *ipc_host_txdesc_get(struct ipc_host_env_tag *env, const int queue_idx, const int user_pos); /** ****************************************************************************** * @brief Push a filled Tx descriptor (host side). * * This function sets the next Tx descriptor available by the host side: * - as used for the host side * - as available for the emb side. * The Tx descriptor must be correctly filled before calling this function. * * This function may trigger an IRQ to the emb CPU depending on the interrupt * mitigation policy and on the push count. * * @param[in] env Pointer to the IPC host environment * @param[in] queue_idx Queue index. Same value than ipc_host_txdesc_get() * @param[in] user_pos User position. If MU-MIMO is not used, this value * shall be 0. * @param[in] host_id Parameter indicated by the IPC at TX confirmation, * that allows the driver finding the buffer * ****************************************************************************** */ void ipc_host_txdesc_push(struct ipc_host_env_tag *env, const int queue_idx, const int user_pos, void *host_id); /** ****************************************************************************** * @brief Check if there are TX frames pending in the TX queues. * * @param[in] env Pointer to the IPC host environment * * @return true if there are frames pending, false otherwise. * ****************************************************************************** */ bool ipc_host_tx_frames_pending(struct ipc_host_env_tag *env); /** ****************************************************************************** * @brief Get and flush a packet from the IPC queue passed as parameter. * * @param[in] env Pointer to the IPC host environment * @param[in] queue_idx Index of the queue to flush * @param[in] user_pos User position to flush * * @return The flushed hostid if there is one, 0 otherwise. * ****************************************************************************** */ void *ipc_host_tx_flush(struct ipc_host_env_tag *env, const int queue_idx, const int user_pos); /// @} IPC_TX /** @addtogroup IPC_RX * @{ */ void ipc_host_patt_addr_push(struct ipc_host_env_tag *env, uint32_t addr); /** ****************************************************************************** * @brief Push a pre-allocated buffer descriptor for Rx packet (host side) * * This function should be called by the host IRQ handler to supply the * embedded side with new empty buffer. * * @param[in] env Pointer to the IPC host environment * @param[in] hostid Packet ID used by the host (skbuff pointer on Linux) * @param[in] hostbuf Pointer to the start of the buffer payload in the * host memory (this may be inferred from the skbuff?) * The length of this buffer should be predefined * between host and emb statically (constant needed?). * ****************************************************************************** */ int ipc_host_rxbuf_push(struct ipc_host_env_tag *env, #ifdef CONFIG_ECRNX_SOFTMAC void *hostid, #else uint32_t hostid, #endif uint32_t hostbuf); /** ****************************************************************************** * @brief Push a pre-allocated Descriptor * * This function should be called by the host IRQ handler to supply the * embedded side with new empty buffer. * * @param[in] env Pointer to the IPC host environment * @param[in] hostid Address of packet for host * @param[in] hostbuf Pointer to the start of the buffer payload in the * host memory. The length of this buffer should be * predefined between host and emb statically. * ****************************************************************************** */ int ipc_host_rxdesc_push(struct ipc_host_env_tag *env, void *hostid, uint32_t hostbuf); /** ****************************************************************************** * @brief Push a pre-allocated radar event buffer descriptor * * This function is called at Init time to initialize all radar event buffers. * Then each time embedded send a radar event, this function is used to push * back the same buffer once it has been handled. * * @param[in] env Pointer to the IPC host environment * @param[in] hostid Address of packet for host * @param[in] hostbuf Pointer to the start of the buffer payload in the * host memory. The length of this buffer should be * predefined between host and emb statically. * ****************************************************************************** */ int ipc_host_radarbuf_push(struct ipc_host_env_tag *env, void *hostid, uint32_t hostbuf); /** ****************************************************************************** * @brief Push a pre-allocated unsupported rx vector buffer descriptor * * This function is called at Init time to initialize all unsupported rx vector * buffers. Then each time the embedded sends a unsupported rx vector, this * function is used to push a new unsupported rx vector buffer. * * @param[in] env Pointer to the IPC host environment * @param[in] hostid Address of packet for host * @param[in] hostbuf Pointer to the start of the buffer payload in the * host memory. The length of this buffer should be * predefined between host and emb statically. * ****************************************************************************** */ int ipc_host_unsup_rx_vec_buf_push(struct ipc_host_env_tag *env, void *hostid, uint32_t hostbuf); /** ****************************************************************************** * @brief Push a pre-allocated buffer descriptor for IPC MSGs (host side) * * This function is called at Init time to initialize all Emb2App messages * buffers. Then each time embedded send a IPC message, this function is used * to push back the same buffer once it has been handled. * * @param[in] env Pointer to the IPC host environment * @param[in] hostid Address of buffer for host * @param[in] hostbuf Address of buffer for embedded * The length of this buffer should be predefined * between host and emb statically. * ****************************************************************************** */ int ipc_host_msgbuf_push(struct ipc_host_env_tag *env, void *hostid, uint64_t hostbuf); /** ****************************************************************************** * @brief Push a pre-allocated buffer descriptor for Debug messages (host side) * * This function is called at Init time to initialize all debug messages. * Then each time embedded send a debug message, this function is used to push * back the same buffer once it has been handled. * * @param[in] env Pointer to the IPC host environment * @param[in] hostid Address of buffer for host * @param[in] hostbuf Address of buffer for embedded * The length of this buffer should be predefined * between host and emb statically. * ****************************************************************************** */ int ipc_host_dbgbuf_push(struct ipc_host_env_tag *env, void *hostid, uint64_t hostbuf); /** ****************************************************************************** * @brief Push the pre-allocated logic analyzer and debug information buffer * * @param[in] env Pointer to the IPC host environment * @param[in] infobuf Address of buffer for embedded * The length of this buffer should be predefined * between host and emb statically. * ****************************************************************************** */ void ipc_host_dbginfobuf_push(struct ipc_host_env_tag *env, uint32_t infobuf); /// @} IPC_RX /** @addtogroup IPC_MISC * @{ */ /** ****************************************************************************** * @brief Handle all IPC interrupts on the host side. * * The following interrupts should be handled: * Tx confirmation, Rx buffer requests, Rx packet ready and kernel messages * * @param[in] env Pointer to the IPC host environment * ****************************************************************************** */ void ipc_host_irq(struct ipc_host_env_tag *env, uint32_t status); /** ****************************************************************************** * @brief Send a message to the embedded side * * @param[in] env Pointer to the IPC host environment * @param[in] msg_buf Pointer to the message buffer * @param[in] msg_len Length of the message to be transmitted * * @return Non-null value on failure * ****************************************************************************** */ int ipc_host_msg_push(struct ipc_host_env_tag *env, void *msg_buf, uint16_t len); /** ****************************************************************************** * @brief Enable IPC interrupts * * @param[in] env Global ipc_host environment pointer * @param[in] value Bitfield of the interrupts to enable * * @warning After calling this function, IPC interrupts can be triggered at any * time. Potentially, an interrupt could happen even before returning from the * function if there is a request pending from the embedded side. * ****************************************************************************** */ void ipc_host_enable_irq(struct ipc_host_env_tag *env, uint32_t value); void ipc_host_disable_irq(struct ipc_host_env_tag *env, uint32_t value); uint32_t ipc_host_get_status(struct ipc_host_env_tag *env); uint32_t ipc_host_get_rawstatus(struct ipc_host_env_tag *env); /// @} IPC_MISC #endif // _IPC_HOST_H_