blob: a6625354ddeb6514ad5281fb0656d85241b90ee1 [file] [log] [blame]
/*
<:copyright-BRCM:2016:DUAL/GPL:standard
Broadcom Proprietary and Confidential.(c) 2016 Broadcom
All Rights Reserved
Unless you and Broadcom execute a separate written software license
agreement governing use of this software, this software is licensed
to you under the terms of the GNU General Public License version 2
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
with the following added to such license:
As a special exception, the copyright holders of this software give
you permission to link this software with independent modules, and
to copy and distribute the resulting executable under terms of your
choice, provided that you also meet, for each linked independent
module, the terms and conditions of the license of that module.
An independent module is a module which is not derived from this
software. The special exception does not apply to any modifications
of the software.
Not withstanding the above, under no circumstances may you combine
this software in any way with any other Broadcom software provided
under a license other than the GPL, without Broadcom's express prior
written consent.
:>
*/
#ifndef BCMTR_HEADER_H_
#define BCMTR_HEADER_H_
#include <bcmolt_buf.h>
#include <bcmolt_msg_pack.h>
/** Endianess of numbers written to the transport buffer.
* Currently bcmolt_buf service doesn't support setting
* endianness dynamically. Transport buffer direction must be the same
* as selected at compile time in bcmolt_buf.h
*/
#define BCMTR_BUF_ENDIAN BCMOLT_BUF_ENDIAN_FIXED
#define BCMTR_ENDIAN_CPU_TO_BUF_U32(n) BCMOLT_BUF_ENDIAN_CPU_TO_BUF(U32, n)
#define BCMTR_ENDIAN_BUF_TO_CPU_U32(n) BCMOLT_BUF_ENDIAN_BUF_TO_CPU(U32, n)
/** Transport header.
* Inserted in each packet transmitted on the line
*/
typedef struct bcmtr_hdr
{
bcmolt_msg_dir dir; /**< Message direction: request/response */
bcmos_bool more_fragments; /**< TRUE=more fragments to follow */
bcmos_bool auto_proxy_reg; /**< TRUE=message is auto / proxy registration */
bcmos_bool auto_proxy_unreg;/**< TRUE=message is auto / proxy un-registration */
uint8_t instance; /**< Message instance */
bcmolt_group_id msg_id; /**< Message id: object+group+subgroup */
uint16_t corr_tag; /**< correlation tag */
uint16_t frag_number; /**< fragment number */
} bcmtr_hdr;
#define BCMTR_HDR_SIZE 8
/* Shifts and widths of transport header fields */
#define BCMTR_HDR_DIR_S 31
#define BCMTR_HDR_DIR_W 1
#define BCMTR_HDR_REG_S 26
#define BCMTR_HDR_REG_W 1
#define BCMTR_HDR_UNREG_S 25
#define BCMTR_HDR_UNREG_W 1
#define BCMTR_HDR_MORE_FRAGS_S 24
#define BCMTR_HDR_MORE_FRAGS_W 1
#define BCMTR_HDR_INSTANCE_S 16
#define BCMTR_HDR_INSTANCE_W 8
#define BCMTR_HDR_MSG_ID_S 0
#define BCMTR_HDR_MSG_ID_W 16
#define BCMTR_HDR_CORR_TAG_S 16
#define BCMTR_HDR_CORR_TAG_W 16
#define BCMTR_HDR_FRAG_S 0
#define BCMTR_HDR_FRAG_W 16
/* Pack transport header
*
* \param[in] hdr Unpacked transport header
* \param[out] packed_hdr Packed header
*/
static inline void bcmtr_header_pack(const bcmtr_hdr *hdr, uint8_t *packed_hdr)
{
uint32_t w[2];
w[0] = (hdr->dir << BCMTR_HDR_DIR_S) |
(hdr->more_fragments << BCMTR_HDR_MORE_FRAGS_S) |
(hdr->instance << BCMTR_HDR_INSTANCE_S) |
(hdr->auto_proxy_reg << BCMTR_HDR_REG_S) |
(hdr->auto_proxy_unreg << BCMTR_HDR_UNREG_S) |
hdr->msg_id;
w[1] = (hdr->corr_tag << BCMTR_HDR_CORR_TAG_S) | hdr->frag_number;
w[0] = BCMTR_ENDIAN_CPU_TO_BUF_U32(w[0]);
w[1] = BCMTR_ENDIAN_CPU_TO_BUF_U32(w[1]);
memcpy(packed_hdr, w, BCMTR_HDR_SIZE);
}
/* Unpack transport header
*
* \param[in] packed_hdr Packed header
* \param[out] hdr Unpacked transport header
* Buffer current pointer is incremented by the header side.
*/
static inline void bcmtr_header_unpack(const uint8_t *packed_hdr, bcmtr_hdr *hdr)
{
uint32_t w[2];
memcpy(w, packed_hdr, BCMTR_HDR_SIZE);
w[0] = BCMTR_ENDIAN_BUF_TO_CPU_U32(w[0]);
w[1] = BCMTR_ENDIAN_BUF_TO_CPU_U32(w[1]);
hdr->dir = BCM_FIELD_GET(w[0], BCMTR_HDR_DIR);
hdr->more_fragments = BCM_FIELD_GET(w[0], BCMTR_HDR_MORE_FRAGS);
hdr->instance = BCM_FIELD_GET(w[0], BCMTR_HDR_INSTANCE);
hdr->msg_id = BCM_FIELD_GET(w[0], BCMTR_HDR_MSG_ID);
hdr->auto_proxy_reg = BCM_FIELD_GET(w[0], BCMTR_HDR_REG);
hdr->auto_proxy_unreg = BCM_FIELD_GET(w[0], BCMTR_HDR_UNREG);
hdr->corr_tag = BCM_FIELD_GET(w[1], BCMTR_HDR_CORR_TAG);
hdr->frag_number = BCM_FIELD_GET(w[1], BCMTR_HDR_FRAG);
}
/* Fill transport header
*/
static inline bcmos_errno bcmtr_header_fill(const bcmolt_msg *msg, bcmtr_hdr *hdr)
{
bcmos_errno err;
hdr->dir = msg->dir;
hdr->more_fragments = BCMOS_FALSE;
err = bcmolt_group_id_combine(msg->obj_type, msg->group, msg->subgroup, &hdr->msg_id);
if (err)
return err;
hdr->instance = bcmolt_msg_instance(msg);
hdr->corr_tag = msg->corr_tag;
hdr->frag_number = 0;
return BCM_ERR_OK;
}
#endif /* BCMTR_HEADER_H_ */