xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_utils.c (revision f634204b7ad8b58fd8bbbf644ba4bd52d565baf8)
188badb3aSMike Baucom /* SPDX-License-Identifier: BSD-3-Clause
22addc463SAjit Khaparde  * Copyright(c) 2014-2021 Broadcom
388badb3aSMike Baucom  * All rights reserved.
488badb3aSMike Baucom  */
588badb3aSMike Baucom 
688badb3aSMike Baucom #include "ulp_utils.h"
788badb3aSMike Baucom #include "bnxt_tf_common.h"
888badb3aSMike Baucom 
988badb3aSMike Baucom /*
1088badb3aSMike Baucom  * Initialize the regfile structure for writing
1188badb3aSMike Baucom  *
1288badb3aSMike Baucom  * regfile [in] Ptr to a regfile instance
1388badb3aSMike Baucom  *
1488badb3aSMike Baucom  * returns 0 on error or 1 on success
1588badb3aSMike Baucom  */
1688badb3aSMike Baucom uint32_t
1788badb3aSMike Baucom ulp_regfile_init(struct ulp_regfile *regfile)
1888badb3aSMike Baucom {
1988badb3aSMike Baucom 	/* validate the arguments */
2088badb3aSMike Baucom 	if (!regfile) {
2188badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
2288badb3aSMike Baucom 		return 0; /* failure */
2388badb3aSMike Baucom 	}
2488badb3aSMike Baucom 	memset(regfile, 0, sizeof(struct ulp_regfile));
2588badb3aSMike Baucom 	return 1; /* Success */
2688badb3aSMike Baucom }
2788badb3aSMike Baucom 
2888badb3aSMike Baucom /*
2988badb3aSMike Baucom  * Read a value from the regfile
3088badb3aSMike Baucom  *
3188badb3aSMike Baucom  * regfile [in] The regfile instance. Must be initialized prior to being used
3288badb3aSMike Baucom  *
3388badb3aSMike Baucom  * field [in] The field to be read within the regfile.
3488badb3aSMike Baucom  *
3588badb3aSMike Baucom  * data [in/out]
3688badb3aSMike Baucom  *
3788badb3aSMike Baucom  * returns size, zero on failure
3888badb3aSMike Baucom  */
3988badb3aSMike Baucom uint32_t
4088badb3aSMike Baucom ulp_regfile_read(struct ulp_regfile *regfile,
4188badb3aSMike Baucom 		 enum bnxt_ulp_regfile_index field,
4288badb3aSMike Baucom 		 uint64_t *data)
4388badb3aSMike Baucom {
4488badb3aSMike Baucom 	/* validate the arguments */
4588badb3aSMike Baucom 	if (!regfile || field >= BNXT_ULP_REGFILE_INDEX_LAST) {
4688badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
4788badb3aSMike Baucom 		return 0; /* failure */
4888badb3aSMike Baucom 	}
4988badb3aSMike Baucom 
5088badb3aSMike Baucom 	*data = regfile->entry[field].data;
5188badb3aSMike Baucom 	return sizeof(*data);
5288badb3aSMike Baucom }
5388badb3aSMike Baucom 
5488badb3aSMike Baucom /*
5588badb3aSMike Baucom  * Write a value to the regfile
5688badb3aSMike Baucom  *
5788badb3aSMike Baucom  * regfile [in] The regfile instance.  Must be initialized prior to being used
5888badb3aSMike Baucom  *
5988badb3aSMike Baucom  * field [in] The field to be written within the regfile.
6088badb3aSMike Baucom  *
6188badb3aSMike Baucom  * data [in] The value is written into this variable.  It is going to be in the
6288badb3aSMike Baucom  * same byte order as it was written.
6388badb3aSMike Baucom  *
6488badb3aSMike Baucom  * size [in] The size in bytes of the value beingritten into this
6588badb3aSMike Baucom  * variable.
6688badb3aSMike Baucom  *
6788badb3aSMike Baucom  * returns 0 on fail
6888badb3aSMike Baucom  */
6988badb3aSMike Baucom uint32_t
7088badb3aSMike Baucom ulp_regfile_write(struct ulp_regfile *regfile,
7188badb3aSMike Baucom 		  enum bnxt_ulp_regfile_index field,
7288badb3aSMike Baucom 		  uint64_t data)
7388badb3aSMike Baucom {
7488badb3aSMike Baucom 	/* validate the arguments */
7588badb3aSMike Baucom 	if (!regfile || field >= BNXT_ULP_REGFILE_INDEX_LAST) {
7688badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
7788badb3aSMike Baucom 		return 0; /* failure */
7888badb3aSMike Baucom 	}
7988badb3aSMike Baucom 
8088badb3aSMike Baucom 	regfile->entry[field].data = data;
8188badb3aSMike Baucom 	return sizeof(data); /* Success */
8288badb3aSMike Baucom }
8388badb3aSMike Baucom 
8488badb3aSMike Baucom static void
8588badb3aSMike Baucom ulp_bs_put_msb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
8688badb3aSMike Baucom {
8788badb3aSMike Baucom 	uint8_t bitoffs = bitpos % 8;
8888badb3aSMike Baucom 	uint16_t index  = bitpos / 8;
8988badb3aSMike Baucom 	uint8_t mask;
9088badb3aSMike Baucom 	uint8_t tmp;
9188badb3aSMike Baucom 	int8_t shift;
9288badb3aSMike Baucom 
9388badb3aSMike Baucom 	tmp = bs[index];
9488badb3aSMike Baucom 	mask = ((uint8_t)-1 >> (8 - bitlen));
9588badb3aSMike Baucom 	shift = 8 - bitoffs - bitlen;
9688badb3aSMike Baucom 	val &= mask;
9788badb3aSMike Baucom 
9888badb3aSMike Baucom 	if (shift >= 0) {
9988badb3aSMike Baucom 		tmp &= ~(mask << shift);
10088badb3aSMike Baucom 		tmp |= val << shift;
10188badb3aSMike Baucom 		bs[index] = tmp;
10288badb3aSMike Baucom 	} else {
10388badb3aSMike Baucom 		tmp &= ~((uint8_t)-1 >> bitoffs);
10488badb3aSMike Baucom 		tmp |= val >> -shift;
10588badb3aSMike Baucom 		bs[index++] = tmp;
10688badb3aSMike Baucom 
10788badb3aSMike Baucom 		tmp = bs[index];
10888badb3aSMike Baucom 		tmp &= ((uint8_t)-1 >> (bitlen - (8 - bitoffs)));
10988badb3aSMike Baucom 		tmp |= val << (8 + shift);
11088badb3aSMike Baucom 		bs[index] = tmp;
11188badb3aSMike Baucom 	}
11288badb3aSMike Baucom }
11388badb3aSMike Baucom 
11488badb3aSMike Baucom static void
11588badb3aSMike Baucom ulp_bs_put_lsb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
11688badb3aSMike Baucom {
11788badb3aSMike Baucom 	uint8_t bitoffs = bitpos % 8;
11888badb3aSMike Baucom 	uint16_t index  = bitpos / 8;
11988badb3aSMike Baucom 	uint8_t mask;
12088badb3aSMike Baucom 	uint8_t tmp;
12188badb3aSMike Baucom 	uint8_t shift;
12288badb3aSMike Baucom 	uint8_t partial;
12388badb3aSMike Baucom 
12488badb3aSMike Baucom 	tmp = bs[index];
12588badb3aSMike Baucom 	shift = bitoffs;
12688badb3aSMike Baucom 
12788badb3aSMike Baucom 	if (bitoffs + bitlen <= 8) {
12888badb3aSMike Baucom 		mask = ((1 << bitlen) - 1) << shift;
12988badb3aSMike Baucom 		tmp &= ~mask;
13088badb3aSMike Baucom 		tmp |= ((val << shift) & mask);
13188badb3aSMike Baucom 		bs[index] = tmp;
13288badb3aSMike Baucom 	} else {
13388badb3aSMike Baucom 		partial = 8 - bitoffs;
13488badb3aSMike Baucom 		mask = ((1 << partial) - 1) << shift;
13588badb3aSMike Baucom 		tmp &= ~mask;
13688badb3aSMike Baucom 		tmp |= ((val << shift) & mask);
13788badb3aSMike Baucom 		bs[index++] = tmp;
13888badb3aSMike Baucom 
13988badb3aSMike Baucom 		val >>= partial;
14088badb3aSMike Baucom 		partial = bitlen - partial;
14188badb3aSMike Baucom 		mask = ((1 << partial) - 1);
14288badb3aSMike Baucom 		tmp = bs[index];
14388badb3aSMike Baucom 		tmp &= ~mask;
14488badb3aSMike Baucom 		tmp |= (val & mask);
14588badb3aSMike Baucom 		bs[index] = tmp;
14688badb3aSMike Baucom 	}
14788badb3aSMike Baucom }
14888badb3aSMike Baucom 
149*f634204bSKishore Padmanabha /*
150*f634204bSKishore Padmanabha  * Add data to the byte array in Little endian format.
151*f634204bSKishore Padmanabha  *
152*f634204bSKishore Padmanabha  * bs [in] The byte array where data is pushed
153*f634204bSKishore Padmanabha  *
154*f634204bSKishore Padmanabha  * pos [in] The offset where data is pushed
155*f634204bSKishore Padmanabha  *
156*f634204bSKishore Padmanabha  * len [in] The number of bits to be added to the data array.
157*f634204bSKishore Padmanabha  *
158*f634204bSKishore Padmanabha  * val [in] The data to be added to the data array.
159*f634204bSKishore Padmanabha  *
160*f634204bSKishore Padmanabha  * returns the number of bits pushed.
161*f634204bSKishore Padmanabha  */
162*f634204bSKishore Padmanabha uint32_t
16388badb3aSMike Baucom ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
16488badb3aSMike Baucom {
16588badb3aSMike Baucom 	int i;
16688badb3aSMike Baucom 	int cnt = (len) / 8;
16788badb3aSMike Baucom 	int tlen = len;
16888badb3aSMike Baucom 
16988badb3aSMike Baucom 	if (cnt > 0 && !(len % 8))
17088badb3aSMike Baucom 		cnt -= 1;
17188badb3aSMike Baucom 
17288badb3aSMike Baucom 	for (i = 0; i < cnt; i++) {
17388badb3aSMike Baucom 		ulp_bs_put_lsb(bs, pos, 8, val[cnt - i]);
17488badb3aSMike Baucom 		pos += 8;
17588badb3aSMike Baucom 		tlen -= 8;
17688badb3aSMike Baucom 	}
17788badb3aSMike Baucom 
17888badb3aSMike Baucom 	/* Handle the remainder bits */
17988badb3aSMike Baucom 	if (tlen)
18088badb3aSMike Baucom 		ulp_bs_put_lsb(bs, pos, tlen, val[0]);
18188badb3aSMike Baucom 	return len;
18288badb3aSMike Baucom }
18388badb3aSMike Baucom 
184*f634204bSKishore Padmanabha /*
185*f634204bSKishore Padmanabha  * Add data to the byte array in Big endian format.
186*f634204bSKishore Padmanabha  *
187*f634204bSKishore Padmanabha  * bs [in] The byte array where data is pushed
188*f634204bSKishore Padmanabha  *
189*f634204bSKishore Padmanabha  * pos [in] The offset where data is pushed
190*f634204bSKishore Padmanabha  *
191*f634204bSKishore Padmanabha  * len [in] The number of bits to be added to the data array.
192*f634204bSKishore Padmanabha  *
193*f634204bSKishore Padmanabha  * val [in] The data to be added to the data array.
194*f634204bSKishore Padmanabha  *
195*f634204bSKishore Padmanabha  * returns the number of bits pushed.
196*f634204bSKishore Padmanabha  */
197*f634204bSKishore Padmanabha uint32_t
19888badb3aSMike Baucom ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
19988badb3aSMike Baucom {
20088badb3aSMike Baucom 	int i;
20188badb3aSMike Baucom 	int cnt = (len + 7) / 8;
20288badb3aSMike Baucom 	int tlen = len;
20388badb3aSMike Baucom 
20488badb3aSMike Baucom 	/* Handle any remainder bits */
20588badb3aSMike Baucom 	int tmp = len % 8;
20688badb3aSMike Baucom 
20788badb3aSMike Baucom 	if (!tmp)
20888badb3aSMike Baucom 		tmp = 8;
20988badb3aSMike Baucom 
21088badb3aSMike Baucom 	ulp_bs_put_msb(bs, pos, tmp, val[0]);
21188badb3aSMike Baucom 
21288badb3aSMike Baucom 	pos += tmp;
21388badb3aSMike Baucom 	tlen -= tmp;
21488badb3aSMike Baucom 
21588badb3aSMike Baucom 	for (i = 1; i < cnt; i++) {
21688badb3aSMike Baucom 		ulp_bs_put_msb(bs, pos, 8, val[i]);
21788badb3aSMike Baucom 		pos += 8;
21888badb3aSMike Baucom 		tlen -= 8;
21988badb3aSMike Baucom 	}
22088badb3aSMike Baucom 
22188badb3aSMike Baucom 	return len;
22288badb3aSMike Baucom }
22388badb3aSMike Baucom 
22488badb3aSMike Baucom /*
22588badb3aSMike Baucom  * Initializes the blob structure for creating binary blob
22688badb3aSMike Baucom  *
22788badb3aSMike Baucom  * blob [in] The blob to be initialized
22888badb3aSMike Baucom  *
22988badb3aSMike Baucom  * bitlen [in] The bit length of the blob
23088badb3aSMike Baucom  *
23188badb3aSMike Baucom  * order [in] The byte order for the blob.  Currently only supporting
23288badb3aSMike Baucom  * big endian.  All fields are packed with this order.
23388badb3aSMike Baucom  *
23488badb3aSMike Baucom  * returns 0 on error or 1 on success
23588badb3aSMike Baucom  */
23688badb3aSMike Baucom uint32_t
23788badb3aSMike Baucom ulp_blob_init(struct ulp_blob *blob,
23888badb3aSMike Baucom 	      uint16_t bitlen,
23988badb3aSMike Baucom 	      enum bnxt_ulp_byte_order order)
24088badb3aSMike Baucom {
24188badb3aSMike Baucom 	/* validate the arguments */
24288badb3aSMike Baucom 	if (!blob || bitlen > (8 * sizeof(blob->data))) {
24388badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
24488badb3aSMike Baucom 		return 0; /* failure */
24588badb3aSMike Baucom 	}
24688badb3aSMike Baucom 	blob->bitlen = bitlen;
24788badb3aSMike Baucom 	blob->byte_order = order;
24888badb3aSMike Baucom 	blob->write_idx = 0;
24988badb3aSMike Baucom 	memset(blob->data, 0, sizeof(blob->data));
25088badb3aSMike Baucom 	return 1; /* Success */
25188badb3aSMike Baucom }
25288badb3aSMike Baucom 
25388badb3aSMike Baucom /*
25488badb3aSMike Baucom  * Add data to the binary blob at the current offset.
25588badb3aSMike Baucom  *
25688badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
25788badb3aSMike Baucom  * be initialized prior to pushing data.
25888badb3aSMike Baucom  *
25988badb3aSMike Baucom  * data [in] A pointer to bytes to be added to the blob.
26088badb3aSMike Baucom  *
26188badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
26288badb3aSMike Baucom  *
26388badb3aSMike Baucom  * The offset of the data is updated after each push of data.
26488badb3aSMike Baucom  * NULL returned on error.
26588badb3aSMike Baucom  */
26688badb3aSMike Baucom #define ULP_BLOB_BYTE		8
26788badb3aSMike Baucom #define ULP_BLOB_BYTE_HEX	0xFF
26888badb3aSMike Baucom #define BLOB_MASK_CAL(x)	((0xFF << (x)) & 0xFF)
26988badb3aSMike Baucom uint32_t
27088badb3aSMike Baucom ulp_blob_push(struct ulp_blob *blob,
27188badb3aSMike Baucom 	      uint8_t *data,
27288badb3aSMike Baucom 	      uint32_t datalen)
27388badb3aSMike Baucom {
27488badb3aSMike Baucom 	uint32_t rc;
27588badb3aSMike Baucom 
27688badb3aSMike Baucom 	/* validate the arguments */
27788badb3aSMike Baucom 	if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
27888badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
27988badb3aSMike Baucom 		return 0; /* failure */
28088badb3aSMike Baucom 	}
28188badb3aSMike Baucom 
28288badb3aSMike Baucom 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
28388badb3aSMike Baucom 		rc = ulp_bs_push_msb(blob->data,
28488badb3aSMike Baucom 				     blob->write_idx,
28588badb3aSMike Baucom 				     datalen,
28688badb3aSMike Baucom 				     data);
28788badb3aSMike Baucom 	else
28888badb3aSMike Baucom 		rc = ulp_bs_push_lsb(blob->data,
28988badb3aSMike Baucom 				     blob->write_idx,
29088badb3aSMike Baucom 				     datalen,
29188badb3aSMike Baucom 				     data);
29288badb3aSMike Baucom 	if (!rc) {
29388badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "Failed ro write blob\n");
29488badb3aSMike Baucom 		return 0;
29588badb3aSMike Baucom 	}
29688badb3aSMike Baucom 	blob->write_idx += datalen;
29788badb3aSMike Baucom 	return datalen;
29888badb3aSMike Baucom }
29988badb3aSMike Baucom 
30088badb3aSMike Baucom /*
3017e604e7fSKishore Padmanabha  * Insert data into the binary blob at the given offset.
3027e604e7fSKishore Padmanabha  *
3037e604e7fSKishore Padmanabha  * blob [in] The blob that data is added to.  The blob must
3047e604e7fSKishore Padmanabha  * be initialized prior to pushing data.
3057e604e7fSKishore Padmanabha  *
3067e604e7fSKishore Padmanabha  * offset [in] The offset where the data needs to be inserted.
3077e604e7fSKishore Padmanabha  *
3087e604e7fSKishore Padmanabha  * data [in/out] A pointer to bytes to be added to the blob.
3097e604e7fSKishore Padmanabha  *
3107e604e7fSKishore Padmanabha  * datalen [in] The number of bits to be added to the blob.
3117e604e7fSKishore Padmanabha  *
3127e604e7fSKishore Padmanabha  * The offset of the data is updated after each push of data.
3137e604e7fSKishore Padmanabha  * NULL returned on error.
3147e604e7fSKishore Padmanabha  */
3157e604e7fSKishore Padmanabha uint32_t
3167e604e7fSKishore Padmanabha ulp_blob_insert(struct ulp_blob *blob, uint32_t offset,
3177e604e7fSKishore Padmanabha 		uint8_t *data, uint32_t datalen)
3187e604e7fSKishore Padmanabha {
3197e604e7fSKishore Padmanabha 	uint32_t rc;
3207e604e7fSKishore Padmanabha 	uint8_t local_data[BNXT_ULP_FLMP_BLOB_SIZE];
3217e604e7fSKishore Padmanabha 	uint16_t mov_len;
3227e604e7fSKishore Padmanabha 
3237e604e7fSKishore Padmanabha 	/* validate the arguments */
3247e604e7fSKishore Padmanabha 	if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx) ||
3257e604e7fSKishore Padmanabha 	    offset > blob->write_idx) {
3267e604e7fSKishore Padmanabha 		BNXT_TF_DBG(ERR, "invalid argument\n");
3277e604e7fSKishore Padmanabha 		return 0; /* failure */
3287e604e7fSKishore Padmanabha 	}
3297e604e7fSKishore Padmanabha 
3307e604e7fSKishore Padmanabha 	mov_len = blob->write_idx - offset;
3317e604e7fSKishore Padmanabha 	/* If offset and data len are not 8 bit aligned then return error */
3327e604e7fSKishore Padmanabha 	if (ULP_BITS_IS_BYTE_NOT_ALIGNED(offset) ||
3337e604e7fSKishore Padmanabha 	    ULP_BITS_IS_BYTE_NOT_ALIGNED(datalen)) {
3347e604e7fSKishore Padmanabha 		BNXT_TF_DBG(ERR, "invalid argument, not aligned\n");
3357e604e7fSKishore Padmanabha 		return 0; /* failure */
3367e604e7fSKishore Padmanabha 	}
3377e604e7fSKishore Padmanabha 
3387e604e7fSKishore Padmanabha 	/* copy the data so we can move the data */
3397e604e7fSKishore Padmanabha 	memcpy(local_data, &blob->data[ULP_BITS_2_BYTE_NR(offset)],
3407e604e7fSKishore Padmanabha 	       ULP_BITS_2_BYTE(mov_len));
3417e604e7fSKishore Padmanabha 	blob->write_idx = offset;
3427e604e7fSKishore Padmanabha 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
3437e604e7fSKishore Padmanabha 		rc = ulp_bs_push_msb(blob->data,
3447e604e7fSKishore Padmanabha 				     blob->write_idx,
3457e604e7fSKishore Padmanabha 				     datalen,
3467e604e7fSKishore Padmanabha 				     data);
3477e604e7fSKishore Padmanabha 	else
3487e604e7fSKishore Padmanabha 		rc = ulp_bs_push_lsb(blob->data,
3497e604e7fSKishore Padmanabha 				     blob->write_idx,
3507e604e7fSKishore Padmanabha 				     datalen,
3517e604e7fSKishore Padmanabha 				     data);
3527e604e7fSKishore Padmanabha 	if (!rc) {
3537e604e7fSKishore Padmanabha 		BNXT_TF_DBG(ERR, "Failed ro write blob\n");
3547e604e7fSKishore Padmanabha 		return 0;
3557e604e7fSKishore Padmanabha 	}
3567e604e7fSKishore Padmanabha 	/* copy the previously stored data */
3577e604e7fSKishore Padmanabha 	memcpy(&blob->data[ULP_BITS_2_BYTE_NR(offset + datalen)], local_data,
3587e604e7fSKishore Padmanabha 	       ULP_BITS_2_BYTE(mov_len));
3597e604e7fSKishore Padmanabha 	blob->write_idx += (mov_len + datalen);
3607e604e7fSKishore Padmanabha 	return datalen;
3617e604e7fSKishore Padmanabha }
3627e604e7fSKishore Padmanabha 
3637e604e7fSKishore Padmanabha /*
36488badb3aSMike Baucom  * Add data to the binary blob at the current offset.
36588badb3aSMike Baucom  *
36688badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
36788badb3aSMike Baucom  * be initialized prior to pushing data.
36888badb3aSMike Baucom  *
36988badb3aSMike Baucom  * data [in] 64-bit value to be added to the blob.
37088badb3aSMike Baucom  *
37188badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
37288badb3aSMike Baucom  *
37388badb3aSMike Baucom  * The offset of the data is updated after each push of data.
37488badb3aSMike Baucom  * NULL returned on error, pointer pushed value otherwise.
37588badb3aSMike Baucom  */
37688badb3aSMike Baucom uint8_t *
37788badb3aSMike Baucom ulp_blob_push_64(struct ulp_blob *blob,
37888badb3aSMike Baucom 		 uint64_t *data,
37988badb3aSMike Baucom 		 uint32_t datalen)
38088badb3aSMike Baucom {
38188badb3aSMike Baucom 	uint8_t *val = (uint8_t *)data;
38288badb3aSMike Baucom 	int rc;
38388badb3aSMike Baucom 
38488badb3aSMike Baucom 	int size = (datalen + 7) / 8;
38588badb3aSMike Baucom 
38688badb3aSMike Baucom 	if (!blob || !data ||
38788badb3aSMike Baucom 	    datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
38888badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
38988badb3aSMike Baucom 		return 0;
39088badb3aSMike Baucom 	}
39188badb3aSMike Baucom 
39288badb3aSMike Baucom 	rc = ulp_blob_push(blob, &val[8 - size], datalen);
39388badb3aSMike Baucom 	if (!rc)
39488badb3aSMike Baucom 		return 0;
39588badb3aSMike Baucom 
39688badb3aSMike Baucom 	return &val[8 - size];
39788badb3aSMike Baucom }
39888badb3aSMike Baucom 
39988badb3aSMike Baucom /*
400a2be13e1SKishore Padmanabha  * Add data to the binary blob at the current offset.
401a2be13e1SKishore Padmanabha  *
402a2be13e1SKishore Padmanabha  * blob [in] The blob that data is added to.  The blob must
403a2be13e1SKishore Padmanabha  * be initialized prior to pushing data.
404a2be13e1SKishore Padmanabha  *
405a2be13e1SKishore Padmanabha  * data [in] 32-bit value to be added to the blob.
406a2be13e1SKishore Padmanabha  *
407a2be13e1SKishore Padmanabha  * datalen [in] The number of bits to be added ot the blob.
408a2be13e1SKishore Padmanabha  *
409a2be13e1SKishore Padmanabha  * The offset of the data is updated after each push of data.
410a2be13e1SKishore Padmanabha  * NULL returned on error, pointer pushed value otherwise.
411a2be13e1SKishore Padmanabha  */
412a2be13e1SKishore Padmanabha uint8_t *
413a2be13e1SKishore Padmanabha ulp_blob_push_32(struct ulp_blob *blob,
414a2be13e1SKishore Padmanabha 		 uint32_t *data,
415a2be13e1SKishore Padmanabha 		 uint32_t datalen)
416a2be13e1SKishore Padmanabha {
417a2be13e1SKishore Padmanabha 	uint8_t *val = (uint8_t *)data;
418a2be13e1SKishore Padmanabha 	uint32_t rc;
419a2be13e1SKishore Padmanabha 	uint32_t size = ULP_BITS_2_BYTE(datalen);
420a2be13e1SKishore Padmanabha 
421a2be13e1SKishore Padmanabha 	if (!data || size > sizeof(uint32_t)) {
422a2be13e1SKishore Padmanabha 		BNXT_TF_DBG(ERR, "invalid argument\n");
423a2be13e1SKishore Padmanabha 		return 0;
424a2be13e1SKishore Padmanabha 	}
425a2be13e1SKishore Padmanabha 
426a2be13e1SKishore Padmanabha 	rc = ulp_blob_push(blob, &val[sizeof(uint32_t) - size], datalen);
427a2be13e1SKishore Padmanabha 	if (!rc)
428a2be13e1SKishore Padmanabha 		return 0;
429a2be13e1SKishore Padmanabha 
430a2be13e1SKishore Padmanabha 	return &val[sizeof(uint32_t) - size];
431a2be13e1SKishore Padmanabha }
432a2be13e1SKishore Padmanabha 
433a2be13e1SKishore Padmanabha /*
43488badb3aSMike Baucom  * Add encap data to the binary blob at the current offset.
43588badb3aSMike Baucom  *
43688badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
43788badb3aSMike Baucom  * be initialized prior to pushing data.
43888badb3aSMike Baucom  *
43988badb3aSMike Baucom  * data [in] value to be added to the blob.
44088badb3aSMike Baucom  *
44188badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
44288badb3aSMike Baucom  *
44388badb3aSMike Baucom  * The offset of the data is updated after each push of data.
44488badb3aSMike Baucom  * NULL returned on error, pointer pushed value otherwise.
44588badb3aSMike Baucom  */
44688badb3aSMike Baucom uint32_t
44788badb3aSMike Baucom ulp_blob_push_encap(struct ulp_blob *blob,
44888badb3aSMike Baucom 		    uint8_t *data,
44988badb3aSMike Baucom 		    uint32_t datalen)
45088badb3aSMike Baucom {
45188badb3aSMike Baucom 	uint8_t		*val = (uint8_t *)data;
45288badb3aSMike Baucom 	uint32_t	initial_size, write_size = datalen;
45388badb3aSMike Baucom 	uint32_t	size = 0;
45488badb3aSMike Baucom 
45588badb3aSMike Baucom 	if (!blob || !data ||
45688badb3aSMike Baucom 	    datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
45788badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
45888badb3aSMike Baucom 		return 0;
45988badb3aSMike Baucom 	}
46088badb3aSMike Baucom 
46188badb3aSMike Baucom 	initial_size = ULP_BYTE_2_BITS(sizeof(uint64_t)) -
46288badb3aSMike Baucom 	    (blob->write_idx % ULP_BYTE_2_BITS(sizeof(uint64_t)));
46388badb3aSMike Baucom 	while (write_size > 0) {
46488badb3aSMike Baucom 		if (initial_size && write_size > initial_size) {
46588badb3aSMike Baucom 			size = initial_size;
46688badb3aSMike Baucom 			initial_size = 0;
46788badb3aSMike Baucom 		} else if (initial_size && write_size <= initial_size) {
46888badb3aSMike Baucom 			size = write_size;
46988badb3aSMike Baucom 			initial_size = 0;
47088badb3aSMike Baucom 		} else if (write_size > ULP_BYTE_2_BITS(sizeof(uint64_t))) {
47188badb3aSMike Baucom 			size = ULP_BYTE_2_BITS(sizeof(uint64_t));
47288badb3aSMike Baucom 		} else {
47388badb3aSMike Baucom 			size = write_size;
47488badb3aSMike Baucom 		}
47588badb3aSMike Baucom 		if (!ulp_blob_push(blob, val, size)) {
47688badb3aSMike Baucom 			BNXT_TF_DBG(ERR, "push field failed\n");
47788badb3aSMike Baucom 			return 0;
47888badb3aSMike Baucom 		}
47988badb3aSMike Baucom 		val += ULP_BITS_2_BYTE(size);
48088badb3aSMike Baucom 		write_size -= size;
48188badb3aSMike Baucom 	}
48288badb3aSMike Baucom 	return datalen;
48388badb3aSMike Baucom }
48488badb3aSMike Baucom 
48588badb3aSMike Baucom /*
48688badb3aSMike Baucom  * Adds pad to an initialized blob at the current offset
48788badb3aSMike Baucom  *
48888badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
48988badb3aSMike Baucom  * be initialized prior to pushing data.
49088badb3aSMike Baucom  *
49188badb3aSMike Baucom  * datalen [in] The number of bits of pad to add
49288badb3aSMike Baucom  *
493a4651725SMike Baucom  * returns the number of pad bits added, -1 on failure
49488badb3aSMike Baucom  */
495a4651725SMike Baucom int32_t
49688badb3aSMike Baucom ulp_blob_pad_push(struct ulp_blob *blob,
49788badb3aSMike Baucom 		  uint32_t datalen)
49888badb3aSMike Baucom {
49988badb3aSMike Baucom 	if (datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
50088badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "Pad too large for blob\n");
501*f634204bSKishore Padmanabha 		return -1;
50288badb3aSMike Baucom 	}
50388badb3aSMike Baucom 
50488badb3aSMike Baucom 	blob->write_idx += datalen;
50588badb3aSMike Baucom 	return datalen;
50688badb3aSMike Baucom }
50788badb3aSMike Baucom 
508afd35335SKishore Padmanabha /* Get data from src and put into dst using little-endian format */
509afd35335SKishore Padmanabha static void
510afd35335SKishore Padmanabha ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
511afd35335SKishore Padmanabha {
512afd35335SKishore Padmanabha 	uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
513afd35335SKishore Padmanabha 	uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
514afd35335SKishore Padmanabha 	uint8_t mask, partial, shift;
515afd35335SKishore Padmanabha 
516afd35335SKishore Padmanabha 	shift = bitoffs;
517afd35335SKishore Padmanabha 	partial = ULP_BLOB_BYTE - bitoffs;
518afd35335SKishore Padmanabha 	if (bitoffs + bitlen <= ULP_BLOB_BYTE) {
519afd35335SKishore Padmanabha 		mask = ((1 << bitlen) - 1) << shift;
520afd35335SKishore Padmanabha 		*dst = (src[index] & mask) >> shift;
521afd35335SKishore Padmanabha 	} else {
522afd35335SKishore Padmanabha 		mask = ((1 << partial) - 1) << shift;
523afd35335SKishore Padmanabha 		*dst = (src[index] & mask) >> shift;
524afd35335SKishore Padmanabha 		index++;
525afd35335SKishore Padmanabha 		partial = bitlen - partial;
526afd35335SKishore Padmanabha 		mask = ((1 << partial) - 1);
527afd35335SKishore Padmanabha 		*dst |= (src[index] & mask) << (ULP_BLOB_BYTE - bitoffs);
528afd35335SKishore Padmanabha 	}
529afd35335SKishore Padmanabha }
530afd35335SKishore Padmanabha 
531*f634204bSKishore Padmanabha /*
532*f634204bSKishore Padmanabha  * Get data from the byte array in Little endian format.
533*f634204bSKishore Padmanabha  *
534*f634204bSKishore Padmanabha  * src [in] The byte array where data is extracted from
535*f634204bSKishore Padmanabha  *
536*f634204bSKishore Padmanabha  * dst [out] The byte array where data is pulled into
537*f634204bSKishore Padmanabha  *
538*f634204bSKishore Padmanabha  * size [in] The size of dst array in bytes
539*f634204bSKishore Padmanabha  *
540*f634204bSKishore Padmanabha  * offset [in] The offset where data is pulled
541*f634204bSKishore Padmanabha  *
542*f634204bSKishore Padmanabha  * len [in] The number of bits to be extracted from the data array
543*f634204bSKishore Padmanabha  *
544*f634204bSKishore Padmanabha  * returns None.
545*f634204bSKishore Padmanabha  */
546*f634204bSKishore Padmanabha void
547afd35335SKishore Padmanabha ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size,
548afd35335SKishore Padmanabha 		uint32_t offset, uint32_t len)
549afd35335SKishore Padmanabha {
550afd35335SKishore Padmanabha 	uint32_t idx;
551afd35335SKishore Padmanabha 	uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
552afd35335SKishore Padmanabha 
553afd35335SKishore Padmanabha 	/* iterate bytewise to get data */
554afd35335SKishore Padmanabha 	for (idx = 0; idx < cnt; idx++) {
555afd35335SKishore Padmanabha 		ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE,
556afd35335SKishore Padmanabha 			       &dst[size - 1 - idx]);
557afd35335SKishore Padmanabha 		offset += ULP_BLOB_BYTE;
558afd35335SKishore Padmanabha 		len -= ULP_BLOB_BYTE;
559afd35335SKishore Padmanabha 	}
560afd35335SKishore Padmanabha 
561afd35335SKishore Padmanabha 	/* Extract the last reminder data that is not 8 byte boundary */
562afd35335SKishore Padmanabha 	if (len)
563afd35335SKishore Padmanabha 		ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]);
564afd35335SKishore Padmanabha }
565afd35335SKishore Padmanabha 
566*f634204bSKishore Padmanabha /* Get data from src and put into dst using big-endian format */
567*f634204bSKishore Padmanabha static void
568*f634204bSKishore Padmanabha ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
569*f634204bSKishore Padmanabha {
570*f634204bSKishore Padmanabha 	uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
571*f634204bSKishore Padmanabha 	uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
572*f634204bSKishore Padmanabha 	uint8_t mask;
573*f634204bSKishore Padmanabha 	int32_t shift;
574*f634204bSKishore Padmanabha 
575*f634204bSKishore Padmanabha 	shift = ULP_BLOB_BYTE - bitoffs - bitlen;
576*f634204bSKishore Padmanabha 	if (shift >= 0) {
577*f634204bSKishore Padmanabha 		mask = 0xFF >> -bitlen;
578*f634204bSKishore Padmanabha 		*dst = (src[index] >> shift) & mask;
579*f634204bSKishore Padmanabha 	} else {
580*f634204bSKishore Padmanabha 		*dst = (src[index] & (0xFF >> bitoffs)) << -shift;
581*f634204bSKishore Padmanabha 		*dst |= src[index + 1] >> -shift;
582*f634204bSKishore Padmanabha 	}
583*f634204bSKishore Padmanabha }
584*f634204bSKishore Padmanabha 
585*f634204bSKishore Padmanabha /*
586*f634204bSKishore Padmanabha  * Get data from the byte array in Big endian format.
587*f634204bSKishore Padmanabha  *
588*f634204bSKishore Padmanabha  * src [in] The byte array where data is extracted from
589*f634204bSKishore Padmanabha  *
590*f634204bSKishore Padmanabha  * dst [out] The byte array where data is pulled into
591*f634204bSKishore Padmanabha  *
592*f634204bSKishore Padmanabha  * offset [in] The offset where data is pulled
593*f634204bSKishore Padmanabha  *
594*f634204bSKishore Padmanabha  * len [in] The number of bits to be extracted from the data array
595*f634204bSKishore Padmanabha  *
596*f634204bSKishore Padmanabha  * returns None.
597*f634204bSKishore Padmanabha  */
598*f634204bSKishore Padmanabha void
599*f634204bSKishore Padmanabha ulp_bs_pull_msb(uint8_t *src, uint8_t *dst,
600*f634204bSKishore Padmanabha 		uint32_t offset, uint32_t len)
601*f634204bSKishore Padmanabha {
602*f634204bSKishore Padmanabha 	uint32_t idx;
603*f634204bSKishore Padmanabha 	uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
604*f634204bSKishore Padmanabha 
605*f634204bSKishore Padmanabha 	/* iterate bytewise to get data */
606*f634204bSKishore Padmanabha 	for (idx = 0; idx < cnt; idx++) {
607*f634204bSKishore Padmanabha 		ulp_bs_get_msb(src, offset, ULP_BLOB_BYTE, &dst[idx]);
608*f634204bSKishore Padmanabha 		offset += ULP_BLOB_BYTE;
609*f634204bSKishore Padmanabha 		len -= ULP_BLOB_BYTE;
610*f634204bSKishore Padmanabha 	}
611*f634204bSKishore Padmanabha 
612*f634204bSKishore Padmanabha 	/* Extract the last reminder data that is not 8 byte boundary */
613*f634204bSKishore Padmanabha 	if (len)
614*f634204bSKishore Padmanabha 		ulp_bs_get_msb(src, offset, len, &dst[idx]);
615*f634204bSKishore Padmanabha }
616*f634204bSKishore Padmanabha 
617afd35335SKishore Padmanabha /*
618afd35335SKishore Padmanabha  * Extract data from the binary blob using given offset.
619afd35335SKishore Padmanabha  *
620afd35335SKishore Padmanabha  * blob [in] The blob that data is extracted from. The blob must
621afd35335SKishore Padmanabha  * be initialized prior to pulling data.
622afd35335SKishore Padmanabha  *
623afd35335SKishore Padmanabha  * data [in] A pointer to put the data.
624afd35335SKishore Padmanabha  * data_size [in] size of the data buffer in bytes.
625afd35335SKishore Padmanabha  *offset [in] - Offset in the blob to extract the data in bits format.
626afd35335SKishore Padmanabha  * len [in] The number of bits to be pulled from the blob.
627afd35335SKishore Padmanabha  *
628afd35335SKishore Padmanabha  * Output: zero on success, -1 on failure
629afd35335SKishore Padmanabha  */
630afd35335SKishore Padmanabha int32_t
631afd35335SKishore Padmanabha ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size,
632afd35335SKishore Padmanabha 	      uint16_t offset, uint16_t len)
633afd35335SKishore Padmanabha {
634afd35335SKishore Padmanabha 	/* validate the arguments */
635afd35335SKishore Padmanabha 	if (!blob || (offset + len) > blob->bitlen ||
636afd35335SKishore Padmanabha 	    ULP_BYTE_2_BITS(data_size) < len) {
637afd35335SKishore Padmanabha 		BNXT_TF_DBG(ERR, "invalid argument\n");
638afd35335SKishore Padmanabha 		return -1; /* failure */
639afd35335SKishore Padmanabha 	}
640afd35335SKishore Padmanabha 
641*f634204bSKishore Padmanabha 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
642*f634204bSKishore Padmanabha 		ulp_bs_pull_msb(blob->data, data, offset, len);
643*f634204bSKishore Padmanabha 	else
644afd35335SKishore Padmanabha 		ulp_bs_pull_lsb(blob->data, data, data_size, offset, len);
645afd35335SKishore Padmanabha 	return 0;
646afd35335SKishore Padmanabha }
647afd35335SKishore Padmanabha 
64888badb3aSMike Baucom /*
64988badb3aSMike Baucom  * Get the data portion of the binary blob.
65088badb3aSMike Baucom  *
65188badb3aSMike Baucom  * blob [in] The blob's data to be retrieved. The blob must be
65288badb3aSMike Baucom  * initialized prior to pushing data.
65388badb3aSMike Baucom  *
65488badb3aSMike Baucom  * datalen [out] The number of bits to that are filled.
65588badb3aSMike Baucom  *
65688badb3aSMike Baucom  * returns a byte array of the blob data.  Returns NULL on error.
65788badb3aSMike Baucom  */
65888badb3aSMike Baucom uint8_t *
65988badb3aSMike Baucom ulp_blob_data_get(struct ulp_blob *blob,
66088badb3aSMike Baucom 		  uint16_t *datalen)
66188badb3aSMike Baucom {
66288badb3aSMike Baucom 	/* validate the arguments */
66388badb3aSMike Baucom 	if (!blob) {
66488badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
66588badb3aSMike Baucom 		return NULL; /* failure */
66688badb3aSMike Baucom 	}
66788badb3aSMike Baucom 	*datalen = blob->write_idx;
66888badb3aSMike Baucom 	return blob->data;
66988badb3aSMike Baucom }
67088badb3aSMike Baucom 
67188badb3aSMike Baucom /*
67288badb3aSMike Baucom  * Set the encap swap start index of the binary blob.
67388badb3aSMike Baucom  *
67488badb3aSMike Baucom  * blob [in] The blob's data to be retrieved. The blob must be
67588badb3aSMike Baucom  * initialized prior to pushing data.
67688badb3aSMike Baucom  *
67788badb3aSMike Baucom  * returns void.
67888badb3aSMike Baucom  */
67988badb3aSMike Baucom void
68088badb3aSMike Baucom ulp_blob_encap_swap_idx_set(struct ulp_blob *blob)
68188badb3aSMike Baucom {
68288badb3aSMike Baucom 	/* validate the arguments */
68388badb3aSMike Baucom 	if (!blob) {
68488badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
68588badb3aSMike Baucom 		return; /* failure */
68688badb3aSMike Baucom 	}
68788badb3aSMike Baucom 	blob->encap_swap_idx = blob->write_idx;
68888badb3aSMike Baucom }
68988badb3aSMike Baucom 
69088badb3aSMike Baucom /*
69188badb3aSMike Baucom  * Perform the encap buffer swap to 64 bit reversal.
69288badb3aSMike Baucom  *
69388badb3aSMike Baucom  * blob [in] The blob's data to be used for swap.
69488badb3aSMike Baucom  *
69588badb3aSMike Baucom  * returns void.
69688badb3aSMike Baucom  */
69788badb3aSMike Baucom void
69888badb3aSMike Baucom ulp_blob_perform_encap_swap(struct ulp_blob *blob)
69988badb3aSMike Baucom {
7009238ac2aSKishore Padmanabha 	uint32_t i, idx = 0, end_idx = 0, roundoff;
70188badb3aSMike Baucom 	uint8_t temp_val_1, temp_val_2;
70288badb3aSMike Baucom 
70388badb3aSMike Baucom 	/* validate the arguments */
70488badb3aSMike Baucom 	if (!blob) {
70588badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
70688badb3aSMike Baucom 		return; /* failure */
70788badb3aSMike Baucom 	}
708f0ca77fdSMike Baucom 	idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx);
70988badb3aSMike Baucom 	end_idx = ULP_BITS_2_BYTE(blob->write_idx);
7109238ac2aSKishore Padmanabha 	roundoff = ULP_BYTE_2_BITS(ULP_BITS_2_BYTE(end_idx));
7119238ac2aSKishore Padmanabha 	if (roundoff > end_idx) {
7129238ac2aSKishore Padmanabha 		blob->write_idx += ULP_BYTE_2_BITS(roundoff - end_idx);
7139238ac2aSKishore Padmanabha 		end_idx = roundoff;
7149238ac2aSKishore Padmanabha 	}
71588badb3aSMike Baucom 	while (idx <= end_idx) {
71688badb3aSMike Baucom 		for (i = 0; i < 4; i = i + 2) {
71788badb3aSMike Baucom 			temp_val_1 = blob->data[idx + i];
71888badb3aSMike Baucom 			temp_val_2 = blob->data[idx + i + 1];
71988badb3aSMike Baucom 			blob->data[idx + i] = blob->data[idx + 6 - i];
72088badb3aSMike Baucom 			blob->data[idx + i + 1] = blob->data[idx + 7 - i];
72188badb3aSMike Baucom 			blob->data[idx + 7 - i] = temp_val_2;
72288badb3aSMike Baucom 			blob->data[idx + 6 - i] = temp_val_1;
72388badb3aSMike Baucom 		}
72488badb3aSMike Baucom 		idx += 8;
72588badb3aSMike Baucom 	}
72688badb3aSMike Baucom }
72788badb3aSMike Baucom 
72888badb3aSMike Baucom /*
729a4651725SMike Baucom  * Perform the blob buffer reversal byte wise.
730a4651725SMike Baucom  * This api makes the first byte the last and
731a4651725SMike Baucom  * vice-versa.
732a4651725SMike Baucom  *
733a4651725SMike Baucom  * blob [in] The blob's data to be used for swap.
734a4651725SMike Baucom  *
735a4651725SMike Baucom  * returns void.
736a4651725SMike Baucom  */
737a4651725SMike Baucom void
738a4651725SMike Baucom ulp_blob_perform_byte_reverse(struct ulp_blob *blob)
739a4651725SMike Baucom {
740a4651725SMike Baucom 	uint32_t idx = 0, num = 0;
741a4651725SMike Baucom 	uint8_t xchar;
742a4651725SMike Baucom 
743a4651725SMike Baucom 	/* validate the arguments */
744a4651725SMike Baucom 	if (!blob) {
745a4651725SMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
746a4651725SMike Baucom 		return; /* failure */
747a4651725SMike Baucom 	}
748a4651725SMike Baucom 
749a4651725SMike Baucom 	num = ULP_BITS_2_BYTE_NR(blob->write_idx);
750a4651725SMike Baucom 	for (idx = 0; idx < (num / 2); idx++) {
751a4651725SMike Baucom 		xchar = blob->data[idx];
752a4651725SMike Baucom 		blob->data[idx] = blob->data[(num - 1) - idx];
753a4651725SMike Baucom 		blob->data[(num - 1) - idx] = xchar;
754a4651725SMike Baucom 	}
755a4651725SMike Baucom }
756a4651725SMike Baucom 
757a4651725SMike Baucom /*
7587e604e7fSKishore Padmanabha  * Perform the blob buffer 64 bit word swap.
7597e604e7fSKishore Padmanabha  * This api makes the first 4 bytes the last in
7607e604e7fSKishore Padmanabha  * a given 64 bit value and vice-versa.
7617e604e7fSKishore Padmanabha  *
7627e604e7fSKishore Padmanabha  * blob [in] The blob's data to be used for swap.
7637e604e7fSKishore Padmanabha  *
7647e604e7fSKishore Padmanabha  * returns void.
7657e604e7fSKishore Padmanabha  */
7667e604e7fSKishore Padmanabha void
7677e604e7fSKishore Padmanabha ulp_blob_perform_64B_word_swap(struct ulp_blob *blob)
7687e604e7fSKishore Padmanabha {
7697e604e7fSKishore Padmanabha 	uint32_t i, j, num;
7707e604e7fSKishore Padmanabha 	uint8_t xchar;
7717e604e7fSKishore Padmanabha 	uint32_t word_size = ULP_64B_IN_BYTES / 2;
7727e604e7fSKishore Padmanabha 
7737e604e7fSKishore Padmanabha 	/* validate the arguments */
7747e604e7fSKishore Padmanabha 	if (!blob) {
7757e604e7fSKishore Padmanabha 		BNXT_TF_DBG(ERR, "invalid argument\n");
7767e604e7fSKishore Padmanabha 		return; /* failure */
7777e604e7fSKishore Padmanabha 	}
7787e604e7fSKishore Padmanabha 	num = ULP_BITS_2_BYTE(blob->write_idx);
7797e604e7fSKishore Padmanabha 	for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
7807e604e7fSKishore Padmanabha 		for (j = 0; j < word_size; j++) {
7817e604e7fSKishore Padmanabha 			xchar = blob->data[i + j];
7827e604e7fSKishore Padmanabha 			blob->data[i + j] = blob->data[i + j + word_size];
7837e604e7fSKishore Padmanabha 			blob->data[i + j + word_size] = xchar;
7847e604e7fSKishore Padmanabha 		}
7857e604e7fSKishore Padmanabha 	}
7867e604e7fSKishore Padmanabha }
7877e604e7fSKishore Padmanabha 
7887e604e7fSKishore Padmanabha /*
7897e604e7fSKishore Padmanabha  * Perform the blob buffer 64 bit byte swap.
7907e604e7fSKishore Padmanabha  * This api makes the first byte the last in
7917e604e7fSKishore Padmanabha  * a given 64 bit value and vice-versa.
7927e604e7fSKishore Padmanabha  *
7937e604e7fSKishore Padmanabha  * blob [in] The blob's data to be used for swap.
7947e604e7fSKishore Padmanabha  *
7957e604e7fSKishore Padmanabha  * returns void.
7967e604e7fSKishore Padmanabha  */
7977e604e7fSKishore Padmanabha void
7987e604e7fSKishore Padmanabha ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob)
7997e604e7fSKishore Padmanabha {
8007e604e7fSKishore Padmanabha 	uint32_t i, j, num;
8017e604e7fSKishore Padmanabha 	uint8_t xchar;
8027e604e7fSKishore Padmanabha 	uint32_t offset = ULP_64B_IN_BYTES - 1;
8037e604e7fSKishore Padmanabha 
8047e604e7fSKishore Padmanabha 	/* validate the arguments */
8057e604e7fSKishore Padmanabha 	if (!blob) {
8067e604e7fSKishore Padmanabha 		BNXT_TF_DBG(ERR, "invalid argument\n");
8077e604e7fSKishore Padmanabha 		return; /* failure */
8087e604e7fSKishore Padmanabha 	}
8097e604e7fSKishore Padmanabha 	num = ULP_BITS_2_BYTE(blob->write_idx);
8107e604e7fSKishore Padmanabha 	for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
8117e604e7fSKishore Padmanabha 		for (j = 0; j < (ULP_64B_IN_BYTES / 2); j++) {
8127e604e7fSKishore Padmanabha 			xchar = blob->data[i + j];
8137e604e7fSKishore Padmanabha 			blob->data[i + j] = blob->data[i + offset - j];
8147e604e7fSKishore Padmanabha 			blob->data[i + offset - j] = xchar;
8157e604e7fSKishore Padmanabha 		}
8167e604e7fSKishore Padmanabha 	}
8177e604e7fSKishore Padmanabha }
8187e604e7fSKishore Padmanabha 
8197e604e7fSKishore Padmanabha /*
82088badb3aSMike Baucom  * Read data from the operand
82188badb3aSMike Baucom  *
82288badb3aSMike Baucom  * operand [in] A pointer to a 16 Byte operand
82388badb3aSMike Baucom  *
82488badb3aSMike Baucom  * val [in/out] The variable to copy the operand to
82588badb3aSMike Baucom  *
82688badb3aSMike Baucom  * bytes [in] The number of bytes to read into val
82788badb3aSMike Baucom  *
82888badb3aSMike Baucom  * returns number of bits read, zero on error
82988badb3aSMike Baucom  */
83088badb3aSMike Baucom uint16_t
83188badb3aSMike Baucom ulp_operand_read(uint8_t *operand,
83288badb3aSMike Baucom 		 uint8_t *val,
83388badb3aSMike Baucom 		 uint16_t bytes)
83488badb3aSMike Baucom {
83588badb3aSMike Baucom 	/* validate the arguments */
83688badb3aSMike Baucom 	if (!operand || !val) {
83788badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
83888badb3aSMike Baucom 		return 0; /* failure */
83988badb3aSMike Baucom 	}
84088badb3aSMike Baucom 	memcpy(val, operand, bytes);
84188badb3aSMike Baucom 	return bytes;
84288badb3aSMike Baucom }
84388badb3aSMike Baucom 
84488badb3aSMike Baucom /*
84588badb3aSMike Baucom  * copy the buffer in the encap format which is 2 bytes.
84688badb3aSMike Baucom  * The MSB of the src is placed at the LSB of dst.
84788badb3aSMike Baucom  *
84888badb3aSMike Baucom  * dst [out] The destination buffer
84988badb3aSMike Baucom  * src [in] The source buffer dst
85088badb3aSMike Baucom  * size[in] size of the buffer.
8519238ac2aSKishore Padmanabha  * align[in] The alignment is either 8 or 16.
85288badb3aSMike Baucom  */
85388badb3aSMike Baucom void
85488badb3aSMike Baucom ulp_encap_buffer_copy(uint8_t *dst,
85588badb3aSMike Baucom 		      const uint8_t *src,
8569238ac2aSKishore Padmanabha 		      uint16_t size,
8579238ac2aSKishore Padmanabha 		      uint16_t align)
85888badb3aSMike Baucom {
8599238ac2aSKishore Padmanabha 	uint16_t	idx, tmp_size = 0;
86088badb3aSMike Baucom 
8619238ac2aSKishore Padmanabha 	do {
8629238ac2aSKishore Padmanabha 		dst += tmp_size;
8639238ac2aSKishore Padmanabha 		src += tmp_size;
8649238ac2aSKishore Padmanabha 		idx = 0;
8659238ac2aSKishore Padmanabha 		if (size > align) {
8669238ac2aSKishore Padmanabha 			tmp_size = align;
8679238ac2aSKishore Padmanabha 			size -= align;
8689238ac2aSKishore Padmanabha 		} else {
8699238ac2aSKishore Padmanabha 			tmp_size = size;
8709238ac2aSKishore Padmanabha 			size = 0;
8719238ac2aSKishore Padmanabha 		}
87288badb3aSMike Baucom 		/* copy 2 bytes at a time. Write MSB to LSB */
8739238ac2aSKishore Padmanabha 		while ((idx + sizeof(uint16_t)) <= tmp_size) {
8749238ac2aSKishore Padmanabha 			memcpy(&dst[idx],
8759238ac2aSKishore Padmanabha 			       &src[tmp_size - idx - sizeof(uint16_t)],
87688badb3aSMike Baucom 			       sizeof(uint16_t));
87788badb3aSMike Baucom 			idx += sizeof(uint16_t);
87888badb3aSMike Baucom 		}
8799238ac2aSKishore Padmanabha 	} while (size);
88088badb3aSMike Baucom }
88188badb3aSMike Baucom 
88288badb3aSMike Baucom /*
88388badb3aSMike Baucom  * Check the buffer is empty
88488badb3aSMike Baucom  *
88588badb3aSMike Baucom  * buf [in] The buffer
88688badb3aSMike Baucom  * size [in] The size of the buffer
88788badb3aSMike Baucom  *
88888badb3aSMike Baucom  */
88988badb3aSMike Baucom int32_t ulp_buffer_is_empty(const uint8_t *buf, uint32_t size)
89088badb3aSMike Baucom {
89188badb3aSMike Baucom 	return buf[0] == 0 && !memcmp(buf, buf + 1, size - 1);
89288badb3aSMike Baucom }
8932bbcdee8SKishore Padmanabha 
8942bbcdee8SKishore Padmanabha /* Function to check if bitmap is zero.Return 1 on success */
8952bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_is_zero(uint8_t *bitmap, int32_t size)
8962bbcdee8SKishore Padmanabha {
8972bbcdee8SKishore Padmanabha 	while (size-- > 0) {
8982bbcdee8SKishore Padmanabha 		if (*bitmap != 0)
8992bbcdee8SKishore Padmanabha 			return 0;
9002bbcdee8SKishore Padmanabha 		bitmap++;
9012bbcdee8SKishore Padmanabha 	}
9022bbcdee8SKishore Padmanabha 	return 1;
9032bbcdee8SKishore Padmanabha }
9042bbcdee8SKishore Padmanabha 
9052bbcdee8SKishore Padmanabha /* Function to check if bitmap is ones. Return 1 on success */
9062bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size)
9072bbcdee8SKishore Padmanabha {
9082bbcdee8SKishore Padmanabha 	while (size-- > 0) {
9092bbcdee8SKishore Padmanabha 		if (*bitmap != 0xFF)
9102bbcdee8SKishore Padmanabha 			return 0;
9112bbcdee8SKishore Padmanabha 		bitmap++;
9122bbcdee8SKishore Padmanabha 	}
9132bbcdee8SKishore Padmanabha 	return 1;
9142bbcdee8SKishore Padmanabha }
9152bbcdee8SKishore Padmanabha 
9162bbcdee8SKishore Padmanabha /* Function to check if bitmap is not zero. Return 1 on success */
9172bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_notzero(uint8_t *bitmap, int32_t size)
9182bbcdee8SKishore Padmanabha {
9192bbcdee8SKishore Padmanabha 	while (size-- > 0) {
9202bbcdee8SKishore Padmanabha 		if (*bitmap != 0)
9212bbcdee8SKishore Padmanabha 			return 1;
9222bbcdee8SKishore Padmanabha 		bitmap++;
9232bbcdee8SKishore Padmanabha 	}
9242bbcdee8SKishore Padmanabha 	return 0;
9252bbcdee8SKishore Padmanabha }
926