xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_utils.c (revision a2be13e175788449d94e12216bfcba5bd780d15b)
188badb3aSMike Baucom /* SPDX-License-Identifier: BSD-3-Clause
288badb3aSMike Baucom  * Copyright(c) 2014-2019 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 
14988badb3aSMike Baucom /* Assuming that val is in Big-Endian Format */
15088badb3aSMike Baucom static uint32_t
15188badb3aSMike Baucom ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
15288badb3aSMike Baucom {
15388badb3aSMike Baucom 	int i;
15488badb3aSMike Baucom 	int cnt = (len) / 8;
15588badb3aSMike Baucom 	int tlen = len;
15688badb3aSMike Baucom 
15788badb3aSMike Baucom 	if (cnt > 0 && !(len % 8))
15888badb3aSMike Baucom 		cnt -= 1;
15988badb3aSMike Baucom 
16088badb3aSMike Baucom 	for (i = 0; i < cnt; i++) {
16188badb3aSMike Baucom 		ulp_bs_put_lsb(bs, pos, 8, val[cnt - i]);
16288badb3aSMike Baucom 		pos += 8;
16388badb3aSMike Baucom 		tlen -= 8;
16488badb3aSMike Baucom 	}
16588badb3aSMike Baucom 
16688badb3aSMike Baucom 	/* Handle the remainder bits */
16788badb3aSMike Baucom 	if (tlen)
16888badb3aSMike Baucom 		ulp_bs_put_lsb(bs, pos, tlen, val[0]);
16988badb3aSMike Baucom 	return len;
17088badb3aSMike Baucom }
17188badb3aSMike Baucom 
17288badb3aSMike Baucom /* Assuming that val is in Big-Endian Format */
17388badb3aSMike Baucom static uint32_t
17488badb3aSMike Baucom ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
17588badb3aSMike Baucom {
17688badb3aSMike Baucom 	int i;
17788badb3aSMike Baucom 	int cnt = (len + 7) / 8;
17888badb3aSMike Baucom 	int tlen = len;
17988badb3aSMike Baucom 
18088badb3aSMike Baucom 	/* Handle any remainder bits */
18188badb3aSMike Baucom 	int tmp = len % 8;
18288badb3aSMike Baucom 
18388badb3aSMike Baucom 	if (!tmp)
18488badb3aSMike Baucom 		tmp = 8;
18588badb3aSMike Baucom 
18688badb3aSMike Baucom 	ulp_bs_put_msb(bs, pos, tmp, val[0]);
18788badb3aSMike Baucom 
18888badb3aSMike Baucom 	pos += tmp;
18988badb3aSMike Baucom 	tlen -= tmp;
19088badb3aSMike Baucom 
19188badb3aSMike Baucom 	for (i = 1; i < cnt; i++) {
19288badb3aSMike Baucom 		ulp_bs_put_msb(bs, pos, 8, val[i]);
19388badb3aSMike Baucom 		pos += 8;
19488badb3aSMike Baucom 		tlen -= 8;
19588badb3aSMike Baucom 	}
19688badb3aSMike Baucom 
19788badb3aSMike Baucom 	return len;
19888badb3aSMike Baucom }
19988badb3aSMike Baucom 
20088badb3aSMike Baucom /*
20188badb3aSMike Baucom  * Initializes the blob structure for creating binary blob
20288badb3aSMike Baucom  *
20388badb3aSMike Baucom  * blob [in] The blob to be initialized
20488badb3aSMike Baucom  *
20588badb3aSMike Baucom  * bitlen [in] The bit length of the blob
20688badb3aSMike Baucom  *
20788badb3aSMike Baucom  * order [in] The byte order for the blob.  Currently only supporting
20888badb3aSMike Baucom  * big endian.  All fields are packed with this order.
20988badb3aSMike Baucom  *
21088badb3aSMike Baucom  * returns 0 on error or 1 on success
21188badb3aSMike Baucom  */
21288badb3aSMike Baucom uint32_t
21388badb3aSMike Baucom ulp_blob_init(struct ulp_blob *blob,
21488badb3aSMike Baucom 	      uint16_t bitlen,
21588badb3aSMike Baucom 	      enum bnxt_ulp_byte_order order)
21688badb3aSMike Baucom {
21788badb3aSMike Baucom 	/* validate the arguments */
21888badb3aSMike Baucom 	if (!blob || bitlen > (8 * sizeof(blob->data))) {
21988badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
22088badb3aSMike Baucom 		return 0; /* failure */
22188badb3aSMike Baucom 	}
22288badb3aSMike Baucom 	blob->bitlen = bitlen;
22388badb3aSMike Baucom 	blob->byte_order = order;
22488badb3aSMike Baucom 	blob->write_idx = 0;
22588badb3aSMike Baucom 	memset(blob->data, 0, sizeof(blob->data));
22688badb3aSMike Baucom 	return 1; /* Success */
22788badb3aSMike Baucom }
22888badb3aSMike Baucom 
22988badb3aSMike Baucom /*
23088badb3aSMike Baucom  * Add data to the binary blob at the current offset.
23188badb3aSMike Baucom  *
23288badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
23388badb3aSMike Baucom  * be initialized prior to pushing data.
23488badb3aSMike Baucom  *
23588badb3aSMike Baucom  * data [in] A pointer to bytes to be added to the blob.
23688badb3aSMike Baucom  *
23788badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
23888badb3aSMike Baucom  *
23988badb3aSMike Baucom  * The offset of the data is updated after each push of data.
24088badb3aSMike Baucom  * NULL returned on error.
24188badb3aSMike Baucom  */
24288badb3aSMike Baucom #define ULP_BLOB_BYTE		8
24388badb3aSMike Baucom #define ULP_BLOB_BYTE_HEX	0xFF
24488badb3aSMike Baucom #define BLOB_MASK_CAL(x)	((0xFF << (x)) & 0xFF)
24588badb3aSMike Baucom uint32_t
24688badb3aSMike Baucom ulp_blob_push(struct ulp_blob *blob,
24788badb3aSMike Baucom 	      uint8_t *data,
24888badb3aSMike Baucom 	      uint32_t datalen)
24988badb3aSMike Baucom {
25088badb3aSMike Baucom 	uint32_t rc;
25188badb3aSMike Baucom 
25288badb3aSMike Baucom 	/* validate the arguments */
25388badb3aSMike Baucom 	if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
25488badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
25588badb3aSMike Baucom 		return 0; /* failure */
25688badb3aSMike Baucom 	}
25788badb3aSMike Baucom 
25888badb3aSMike Baucom 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
25988badb3aSMike Baucom 		rc = ulp_bs_push_msb(blob->data,
26088badb3aSMike Baucom 				     blob->write_idx,
26188badb3aSMike Baucom 				     datalen,
26288badb3aSMike Baucom 				     data);
26388badb3aSMike Baucom 	else
26488badb3aSMike Baucom 		rc = ulp_bs_push_lsb(blob->data,
26588badb3aSMike Baucom 				     blob->write_idx,
26688badb3aSMike Baucom 				     datalen,
26788badb3aSMike Baucom 				     data);
26888badb3aSMike Baucom 	if (!rc) {
26988badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "Failed ro write blob\n");
27088badb3aSMike Baucom 		return 0;
27188badb3aSMike Baucom 	}
27288badb3aSMike Baucom 	blob->write_idx += datalen;
27388badb3aSMike Baucom 	return datalen;
27488badb3aSMike Baucom }
27588badb3aSMike Baucom 
27688badb3aSMike Baucom /*
27788badb3aSMike Baucom  * Add data to the binary blob at the current offset.
27888badb3aSMike Baucom  *
27988badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
28088badb3aSMike Baucom  * be initialized prior to pushing data.
28188badb3aSMike Baucom  *
28288badb3aSMike Baucom  * data [in] 64-bit value to be added to the blob.
28388badb3aSMike Baucom  *
28488badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
28588badb3aSMike Baucom  *
28688badb3aSMike Baucom  * The offset of the data is updated after each push of data.
28788badb3aSMike Baucom  * NULL returned on error, pointer pushed value otherwise.
28888badb3aSMike Baucom  */
28988badb3aSMike Baucom uint8_t *
29088badb3aSMike Baucom ulp_blob_push_64(struct ulp_blob *blob,
29188badb3aSMike Baucom 		 uint64_t *data,
29288badb3aSMike Baucom 		 uint32_t datalen)
29388badb3aSMike Baucom {
29488badb3aSMike Baucom 	uint8_t *val = (uint8_t *)data;
29588badb3aSMike Baucom 	int rc;
29688badb3aSMike Baucom 
29788badb3aSMike Baucom 	int size = (datalen + 7) / 8;
29888badb3aSMike Baucom 
29988badb3aSMike Baucom 	if (!blob || !data ||
30088badb3aSMike Baucom 	    datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
30188badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
30288badb3aSMike Baucom 		return 0;
30388badb3aSMike Baucom 	}
30488badb3aSMike Baucom 
30588badb3aSMike Baucom 	rc = ulp_blob_push(blob, &val[8 - size], datalen);
30688badb3aSMike Baucom 	if (!rc)
30788badb3aSMike Baucom 		return 0;
30888badb3aSMike Baucom 
30988badb3aSMike Baucom 	return &val[8 - size];
31088badb3aSMike Baucom }
31188badb3aSMike Baucom 
31288badb3aSMike Baucom /*
313*a2be13e1SKishore Padmanabha  * Add data to the binary blob at the current offset.
314*a2be13e1SKishore Padmanabha  *
315*a2be13e1SKishore Padmanabha  * blob [in] The blob that data is added to.  The blob must
316*a2be13e1SKishore Padmanabha  * be initialized prior to pushing data.
317*a2be13e1SKishore Padmanabha  *
318*a2be13e1SKishore Padmanabha  * data [in] 32-bit value to be added to the blob.
319*a2be13e1SKishore Padmanabha  *
320*a2be13e1SKishore Padmanabha  * datalen [in] The number of bits to be added ot the blob.
321*a2be13e1SKishore Padmanabha  *
322*a2be13e1SKishore Padmanabha  * The offset of the data is updated after each push of data.
323*a2be13e1SKishore Padmanabha  * NULL returned on error, pointer pushed value otherwise.
324*a2be13e1SKishore Padmanabha  */
325*a2be13e1SKishore Padmanabha uint8_t *
326*a2be13e1SKishore Padmanabha ulp_blob_push_32(struct ulp_blob *blob,
327*a2be13e1SKishore Padmanabha 		 uint32_t *data,
328*a2be13e1SKishore Padmanabha 		 uint32_t datalen)
329*a2be13e1SKishore Padmanabha {
330*a2be13e1SKishore Padmanabha 	uint8_t *val = (uint8_t *)data;
331*a2be13e1SKishore Padmanabha 	uint32_t rc;
332*a2be13e1SKishore Padmanabha 	uint32_t size = ULP_BITS_2_BYTE(datalen);
333*a2be13e1SKishore Padmanabha 
334*a2be13e1SKishore Padmanabha 	if (!data || size > sizeof(uint32_t)) {
335*a2be13e1SKishore Padmanabha 		BNXT_TF_DBG(ERR, "invalid argument\n");
336*a2be13e1SKishore Padmanabha 		return 0;
337*a2be13e1SKishore Padmanabha 	}
338*a2be13e1SKishore Padmanabha 
339*a2be13e1SKishore Padmanabha 	rc = ulp_blob_push(blob, &val[sizeof(uint32_t) - size], datalen);
340*a2be13e1SKishore Padmanabha 	if (!rc)
341*a2be13e1SKishore Padmanabha 		return 0;
342*a2be13e1SKishore Padmanabha 
343*a2be13e1SKishore Padmanabha 	return &val[sizeof(uint32_t) - size];
344*a2be13e1SKishore Padmanabha }
345*a2be13e1SKishore Padmanabha 
346*a2be13e1SKishore Padmanabha /*
34788badb3aSMike Baucom  * Add encap data to the binary blob at the current offset.
34888badb3aSMike Baucom  *
34988badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
35088badb3aSMike Baucom  * be initialized prior to pushing data.
35188badb3aSMike Baucom  *
35288badb3aSMike Baucom  * data [in] value to be added to the blob.
35388badb3aSMike Baucom  *
35488badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
35588badb3aSMike Baucom  *
35688badb3aSMike Baucom  * The offset of the data is updated after each push of data.
35788badb3aSMike Baucom  * NULL returned on error, pointer pushed value otherwise.
35888badb3aSMike Baucom  */
35988badb3aSMike Baucom uint32_t
36088badb3aSMike Baucom ulp_blob_push_encap(struct ulp_blob *blob,
36188badb3aSMike Baucom 		    uint8_t *data,
36288badb3aSMike Baucom 		    uint32_t datalen)
36388badb3aSMike Baucom {
36488badb3aSMike Baucom 	uint8_t		*val = (uint8_t *)data;
36588badb3aSMike Baucom 	uint32_t	initial_size, write_size = datalen;
36688badb3aSMike Baucom 	uint32_t	size = 0;
36788badb3aSMike Baucom 
36888badb3aSMike Baucom 	if (!blob || !data ||
36988badb3aSMike Baucom 	    datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
37088badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
37188badb3aSMike Baucom 		return 0;
37288badb3aSMike Baucom 	}
37388badb3aSMike Baucom 
37488badb3aSMike Baucom 	initial_size = ULP_BYTE_2_BITS(sizeof(uint64_t)) -
37588badb3aSMike Baucom 	    (blob->write_idx % ULP_BYTE_2_BITS(sizeof(uint64_t)));
37688badb3aSMike Baucom 	while (write_size > 0) {
37788badb3aSMike Baucom 		if (initial_size && write_size > initial_size) {
37888badb3aSMike Baucom 			size = initial_size;
37988badb3aSMike Baucom 			initial_size = 0;
38088badb3aSMike Baucom 		} else if (initial_size && write_size <= initial_size) {
38188badb3aSMike Baucom 			size = write_size;
38288badb3aSMike Baucom 			initial_size = 0;
38388badb3aSMike Baucom 		} else if (write_size > ULP_BYTE_2_BITS(sizeof(uint64_t))) {
38488badb3aSMike Baucom 			size = ULP_BYTE_2_BITS(sizeof(uint64_t));
38588badb3aSMike Baucom 		} else {
38688badb3aSMike Baucom 			size = write_size;
38788badb3aSMike Baucom 		}
38888badb3aSMike Baucom 		if (!ulp_blob_push(blob, val, size)) {
38988badb3aSMike Baucom 			BNXT_TF_DBG(ERR, "push field failed\n");
39088badb3aSMike Baucom 			return 0;
39188badb3aSMike Baucom 		}
39288badb3aSMike Baucom 		val += ULP_BITS_2_BYTE(size);
39388badb3aSMike Baucom 		write_size -= size;
39488badb3aSMike Baucom 	}
39588badb3aSMike Baucom 	return datalen;
39688badb3aSMike Baucom }
39788badb3aSMike Baucom 
39888badb3aSMike Baucom /*
39988badb3aSMike Baucom  * Adds pad to an initialized blob at the current offset
40088badb3aSMike Baucom  *
40188badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
40288badb3aSMike Baucom  * be initialized prior to pushing data.
40388badb3aSMike Baucom  *
40488badb3aSMike Baucom  * datalen [in] The number of bits of pad to add
40588badb3aSMike Baucom  *
40688badb3aSMike Baucom  * returns the number of pad bits added, zero on failure
40788badb3aSMike Baucom  */
40888badb3aSMike Baucom uint32_t
40988badb3aSMike Baucom ulp_blob_pad_push(struct ulp_blob *blob,
41088badb3aSMike Baucom 		  uint32_t datalen)
41188badb3aSMike Baucom {
41288badb3aSMike Baucom 	if (datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
41388badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "Pad too large for blob\n");
41488badb3aSMike Baucom 		return 0;
41588badb3aSMike Baucom 	}
41688badb3aSMike Baucom 
41788badb3aSMike Baucom 	blob->write_idx += datalen;
41888badb3aSMike Baucom 	return datalen;
41988badb3aSMike Baucom }
42088badb3aSMike Baucom 
42188badb3aSMike Baucom /*
42288badb3aSMike Baucom  * Get the data portion of the binary blob.
42388badb3aSMike Baucom  *
42488badb3aSMike Baucom  * blob [in] The blob's data to be retrieved. The blob must be
42588badb3aSMike Baucom  * initialized prior to pushing data.
42688badb3aSMike Baucom  *
42788badb3aSMike Baucom  * datalen [out] The number of bits to that are filled.
42888badb3aSMike Baucom  *
42988badb3aSMike Baucom  * returns a byte array of the blob data.  Returns NULL on error.
43088badb3aSMike Baucom  */
43188badb3aSMike Baucom uint8_t *
43288badb3aSMike Baucom ulp_blob_data_get(struct ulp_blob *blob,
43388badb3aSMike Baucom 		  uint16_t *datalen)
43488badb3aSMike Baucom {
43588badb3aSMike Baucom 	/* validate the arguments */
43688badb3aSMike Baucom 	if (!blob) {
43788badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
43888badb3aSMike Baucom 		return NULL; /* failure */
43988badb3aSMike Baucom 	}
44088badb3aSMike Baucom 	*datalen = blob->write_idx;
44188badb3aSMike Baucom 	return blob->data;
44288badb3aSMike Baucom }
44388badb3aSMike Baucom 
44488badb3aSMike Baucom /*
44588badb3aSMike Baucom  * Set the encap swap start index of the binary blob.
44688badb3aSMike Baucom  *
44788badb3aSMike Baucom  * blob [in] The blob's data to be retrieved. The blob must be
44888badb3aSMike Baucom  * initialized prior to pushing data.
44988badb3aSMike Baucom  *
45088badb3aSMike Baucom  * returns void.
45188badb3aSMike Baucom  */
45288badb3aSMike Baucom void
45388badb3aSMike Baucom ulp_blob_encap_swap_idx_set(struct ulp_blob *blob)
45488badb3aSMike Baucom {
45588badb3aSMike Baucom 	/* validate the arguments */
45688badb3aSMike Baucom 	if (!blob) {
45788badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
45888badb3aSMike Baucom 		return; /* failure */
45988badb3aSMike Baucom 	}
46088badb3aSMike Baucom 	blob->encap_swap_idx = blob->write_idx;
46188badb3aSMike Baucom }
46288badb3aSMike Baucom 
46388badb3aSMike Baucom /*
46488badb3aSMike Baucom  * Perform the encap buffer swap to 64 bit reversal.
46588badb3aSMike Baucom  *
46688badb3aSMike Baucom  * blob [in] The blob's data to be used for swap.
46788badb3aSMike Baucom  *
46888badb3aSMike Baucom  * returns void.
46988badb3aSMike Baucom  */
47088badb3aSMike Baucom void
47188badb3aSMike Baucom ulp_blob_perform_encap_swap(struct ulp_blob *blob)
47288badb3aSMike Baucom {
47388badb3aSMike Baucom 	uint32_t		i, idx = 0, end_idx = 0;
47488badb3aSMike Baucom 	uint8_t		temp_val_1, temp_val_2;
47588badb3aSMike Baucom 
47688badb3aSMike Baucom 	/* validate the arguments */
47788badb3aSMike Baucom 	if (!blob) {
47888badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
47988badb3aSMike Baucom 		return; /* failure */
48088badb3aSMike Baucom 	}
48188badb3aSMike Baucom 	idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx + 1);
48288badb3aSMike Baucom 	end_idx = ULP_BITS_2_BYTE(blob->write_idx);
48388badb3aSMike Baucom 
48488badb3aSMike Baucom 	while (idx <= end_idx) {
48588badb3aSMike Baucom 		for (i = 0; i < 4; i = i + 2) {
48688badb3aSMike Baucom 			temp_val_1 = blob->data[idx + i];
48788badb3aSMike Baucom 			temp_val_2 = blob->data[idx + i + 1];
48888badb3aSMike Baucom 			blob->data[idx + i] = blob->data[idx + 6 - i];
48988badb3aSMike Baucom 			blob->data[idx + i + 1] = blob->data[idx + 7 - i];
49088badb3aSMike Baucom 			blob->data[idx + 7 - i] = temp_val_2;
49188badb3aSMike Baucom 			blob->data[idx + 6 - i] = temp_val_1;
49288badb3aSMike Baucom 		}
49388badb3aSMike Baucom 		idx += 8;
49488badb3aSMike Baucom 	}
49588badb3aSMike Baucom }
49688badb3aSMike Baucom 
49788badb3aSMike Baucom /*
49888badb3aSMike Baucom  * Read data from the operand
49988badb3aSMike Baucom  *
50088badb3aSMike Baucom  * operand [in] A pointer to a 16 Byte operand
50188badb3aSMike Baucom  *
50288badb3aSMike Baucom  * val [in/out] The variable to copy the operand to
50388badb3aSMike Baucom  *
50488badb3aSMike Baucom  * bytes [in] The number of bytes to read into val
50588badb3aSMike Baucom  *
50688badb3aSMike Baucom  * returns number of bits read, zero on error
50788badb3aSMike Baucom  */
50888badb3aSMike Baucom uint16_t
50988badb3aSMike Baucom ulp_operand_read(uint8_t *operand,
51088badb3aSMike Baucom 		 uint8_t *val,
51188badb3aSMike Baucom 		 uint16_t bytes)
51288badb3aSMike Baucom {
51388badb3aSMike Baucom 	/* validate the arguments */
51488badb3aSMike Baucom 	if (!operand || !val) {
51588badb3aSMike Baucom 		BNXT_TF_DBG(ERR, "invalid argument\n");
51688badb3aSMike Baucom 		return 0; /* failure */
51788badb3aSMike Baucom 	}
51888badb3aSMike Baucom 	memcpy(val, operand, bytes);
51988badb3aSMike Baucom 	return bytes;
52088badb3aSMike Baucom }
52188badb3aSMike Baucom 
52288badb3aSMike Baucom /*
52388badb3aSMike Baucom  * copy the buffer in the encap format which is 2 bytes.
52488badb3aSMike Baucom  * The MSB of the src is placed at the LSB of dst.
52588badb3aSMike Baucom  *
52688badb3aSMike Baucom  * dst [out] The destination buffer
52788badb3aSMike Baucom  * src [in] The source buffer dst
52888badb3aSMike Baucom  * size[in] size of the buffer.
52988badb3aSMike Baucom  */
53088badb3aSMike Baucom void
53188badb3aSMike Baucom ulp_encap_buffer_copy(uint8_t *dst,
53288badb3aSMike Baucom 		      const uint8_t *src,
53388badb3aSMike Baucom 		      uint16_t size)
53488badb3aSMike Baucom {
53588badb3aSMike Baucom 	uint16_t	idx = 0;
53688badb3aSMike Baucom 
53788badb3aSMike Baucom 	/* copy 2 bytes at a time. Write MSB to LSB */
53888badb3aSMike Baucom 	while ((idx + sizeof(uint16_t)) <= size) {
53988badb3aSMike Baucom 		memcpy(&dst[idx], &src[size - idx - sizeof(uint16_t)],
54088badb3aSMike Baucom 		       sizeof(uint16_t));
54188badb3aSMike Baucom 		idx += sizeof(uint16_t);
54288badb3aSMike Baucom 	}
54388badb3aSMike Baucom }
54488badb3aSMike Baucom 
54588badb3aSMike Baucom /*
54688badb3aSMike Baucom  * Check the buffer is empty
54788badb3aSMike Baucom  *
54888badb3aSMike Baucom  * buf [in] The buffer
54988badb3aSMike Baucom  * size [in] The size of the buffer
55088badb3aSMike Baucom  *
55188badb3aSMike Baucom  */
55288badb3aSMike Baucom int32_t ulp_buffer_is_empty(const uint8_t *buf, uint32_t size)
55388badb3aSMike Baucom {
55488badb3aSMike Baucom 	return buf[0] == 0 && !memcmp(buf, buf + 1, size - 1);
55588badb3aSMike Baucom }
5562bbcdee8SKishore Padmanabha 
5572bbcdee8SKishore Padmanabha /* Function to check if bitmap is zero.Return 1 on success */
5582bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_is_zero(uint8_t *bitmap, int32_t size)
5592bbcdee8SKishore Padmanabha {
5602bbcdee8SKishore Padmanabha 	while (size-- > 0) {
5612bbcdee8SKishore Padmanabha 		if (*bitmap != 0)
5622bbcdee8SKishore Padmanabha 			return 0;
5632bbcdee8SKishore Padmanabha 		bitmap++;
5642bbcdee8SKishore Padmanabha 	}
5652bbcdee8SKishore Padmanabha 	return 1;
5662bbcdee8SKishore Padmanabha }
5672bbcdee8SKishore Padmanabha 
5682bbcdee8SKishore Padmanabha /* Function to check if bitmap is ones. Return 1 on success */
5692bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size)
5702bbcdee8SKishore Padmanabha {
5712bbcdee8SKishore Padmanabha 	while (size-- > 0) {
5722bbcdee8SKishore Padmanabha 		if (*bitmap != 0xFF)
5732bbcdee8SKishore Padmanabha 			return 0;
5742bbcdee8SKishore Padmanabha 		bitmap++;
5752bbcdee8SKishore Padmanabha 	}
5762bbcdee8SKishore Padmanabha 	return 1;
5772bbcdee8SKishore Padmanabha }
5782bbcdee8SKishore Padmanabha 
5792bbcdee8SKishore Padmanabha /* Function to check if bitmap is not zero. Return 1 on success */
5802bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_notzero(uint8_t *bitmap, int32_t size)
5812bbcdee8SKishore Padmanabha {
5822bbcdee8SKishore Padmanabha 	while (size-- > 0) {
5832bbcdee8SKishore Padmanabha 		if (*bitmap != 0)
5842bbcdee8SKishore Padmanabha 			return 1;
5852bbcdee8SKishore Padmanabha 		bitmap++;
5862bbcdee8SKishore Padmanabha 	}
5872bbcdee8SKishore Padmanabha 	return 0;
5882bbcdee8SKishore Padmanabha }
589