xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_utils.h (revision 0c036a1485b9d9163a8fa8059ed5272d060c05e0)
188badb3aSMike Baucom /* SPDX-License-Identifier: BSD-3-Clause
2e6e8f03eSRandy Schacher  * Copyright(c) 2014-2023 Broadcom
388badb3aSMike Baucom  * All rights reserved.
488badb3aSMike Baucom  */
588badb3aSMike Baucom 
688badb3aSMike Baucom #ifndef _ULP_UTILS_H_
788badb3aSMike Baucom #define _ULP_UTILS_H_
888badb3aSMike Baucom 
988badb3aSMike Baucom #include "bnxt.h"
108ce17d56SKishore Padmanabha #include "ulp_template_db_enum.h"
1188badb3aSMike Baucom 
123fe124d2SKishore Padmanabha #define ULP_BUFFER_ALIGN_8_BITS		8
139238ac2aSKishore Padmanabha #define ULP_BUFFER_ALIGN_8_BYTE		8
149238ac2aSKishore Padmanabha #define ULP_BUFFER_ALIGN_16_BYTE	16
15f4a4421cSKishore Padmanabha #define ULP_BUFFER_ALIGN_64_BYTE	64
167e604e7fSKishore Padmanabha #define ULP_64B_IN_BYTES		8
17af50070eSKishore Padmanabha #define ULP_64B_IN_BITS			64
183fe124d2SKishore Padmanabha 
1988badb3aSMike Baucom /*
2088badb3aSMike Baucom  * Macros for bitmap sets and gets
2188badb3aSMike Baucom  * These macros can be used if the val are power of 2.
2288badb3aSMike Baucom  */
2388badb3aSMike Baucom #define ULP_BITMAP_SET(bitmap, val)	((bitmap) |= (val))
2488badb3aSMike Baucom #define ULP_BITMAP_RESET(bitmap, val)	((bitmap) &= ~(val))
2588badb3aSMike Baucom #define ULP_BITMAP_ISSET(bitmap, val)	((bitmap) & (val))
262bbcdee8SKishore Padmanabha #define ULP_BITMAP_CMP(b1, b2)  memcmp(&(b1)->bits, \
2788badb3aSMike Baucom 				&(b2)->bits, sizeof((b1)->bits))
2888badb3aSMike Baucom /*
2988badb3aSMike Baucom  * Macros for bitmap sets and gets
3088badb3aSMike Baucom  * These macros can be used if the val are not power of 2 and
3188badb3aSMike Baucom  * are simple index values.
3288badb3aSMike Baucom  */
3388badb3aSMike Baucom #define ULP_INDEX_BITMAP_SIZE	(sizeof(uint64_t) * 8)
3488badb3aSMike Baucom #define ULP_INDEX_BITMAP_CSET(i)	(1UL << \
3588badb3aSMike Baucom 			((ULP_INDEX_BITMAP_SIZE - 1) - \
3688badb3aSMike Baucom 			((i) % ULP_INDEX_BITMAP_SIZE)))
3788badb3aSMike Baucom 
3888badb3aSMike Baucom #define ULP_INDEX_BITMAP_SET(b, i)	((b) |= \
3988badb3aSMike Baucom 			(1UL << ((ULP_INDEX_BITMAP_SIZE - 1) - \
4088badb3aSMike Baucom 			((i) % ULP_INDEX_BITMAP_SIZE))))
4188badb3aSMike Baucom 
4288badb3aSMike Baucom #define ULP_INDEX_BITMAP_RESET(b, i)	((b) &= \
4388badb3aSMike Baucom 			(~(1UL << ((ULP_INDEX_BITMAP_SIZE - 1) - \
4488badb3aSMike Baucom 			((i) % ULP_INDEX_BITMAP_SIZE)))))
4588badb3aSMike Baucom 
4688badb3aSMike Baucom #define ULP_INDEX_BITMAP_GET(b, i)		(((b) >> \
4788badb3aSMike Baucom 			((ULP_INDEX_BITMAP_SIZE - 1) - \
4888badb3aSMike Baucom 			((i) % ULP_INDEX_BITMAP_SIZE))) & 1)
4988badb3aSMike Baucom 
5088badb3aSMike Baucom #define ULP_DEVICE_PARAMS_INDEX(tid, dev_id)	\
5188badb3aSMike Baucom 	(((tid) << BNXT_ULP_LOG2_MAX_NUM_DEV) | (dev_id))
5288badb3aSMike Baucom 
5388badb3aSMike Baucom /* Macro to convert bytes to bits */
5488badb3aSMike Baucom #define ULP_BYTE_2_BITS(byte_x)		((byte_x) * 8)
5588badb3aSMike Baucom /* Macro to convert bits to bytes */
5688badb3aSMike Baucom #define ULP_BITS_2_BYTE(bits_x)		(((bits_x) + 7) / 8)
5788badb3aSMike Baucom /* Macro to convert bits to bytes with no round off*/
5888badb3aSMike Baucom #define ULP_BITS_2_BYTE_NR(bits_x)	((bits_x) / 8)
5988badb3aSMike Baucom 
60f4a4421cSKishore Padmanabha /* Macro to round off to next multiple of 8*/
61f4a4421cSKishore Padmanabha #define ULP_BYTE_ROUND_OFF_8(x)	(((x) + 7) & ~7)
62f4a4421cSKishore Padmanabha 
637e604e7fSKishore Padmanabha /* Macro to check bits are byte aligned */
647e604e7fSKishore Padmanabha #define ULP_BITS_IS_BYTE_NOT_ALIGNED(x)	((x) % 8)
657e604e7fSKishore Padmanabha 
66dd0191d5SShuanglin Wang /* Macro for word conversion */
67dd0191d5SShuanglin Wang #define ULP_BITS_TO_4_BYTE_WORD(x) (((x) + 31) / 32)
68dd0191d5SShuanglin Wang #define ULP_BITS_TO_32_BYTE_WORD(x) (((x) + 255) / 256)
69dd0191d5SShuanglin Wang #define ULP_BITS_TO_4_BYTE_QWORDS(x) (((x) + 127) / 128)
70dd0191d5SShuanglin Wang #define ULP_BITS_TO_128B_ALIGNED_BYTES(x) ((((x) + 127) / 128) * 16)
71dd0191d5SShuanglin Wang 
722bbcdee8SKishore Padmanabha /* Macros to read the computed fields */
730f772db6SKishore Padmanabha #define ULP_COMP_FLD_IDX_RD(params, idx) \
741993b267SShahaji Bhosle 	rte_be_to_cpu_64((params)->comp_fld[(idx)])
752bbcdee8SKishore Padmanabha 
760f772db6SKishore Padmanabha #define ULP_COMP_FLD_IDX_WR(params, idx, val)	\
771993b267SShahaji Bhosle 	((params)->comp_fld[(idx)] = rte_cpu_to_be_64((uint64_t)(val)))
7888badb3aSMike Baucom /*
7988badb3aSMike Baucom  * Making the blob statically sized to 128 bytes for now.
8088badb3aSMike Baucom  * The blob must be initialized with ulp_blob_init prior to using.
8188badb3aSMike Baucom  */
8288badb3aSMike Baucom #define BNXT_ULP_FLMP_BLOB_SIZE	(128)
8388badb3aSMike Baucom #define BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS	ULP_BYTE_2_BITS(BNXT_ULP_FLMP_BLOB_SIZE)
8488badb3aSMike Baucom struct ulp_blob {
8588badb3aSMike Baucom 	enum bnxt_ulp_byte_order	byte_order;
8688badb3aSMike Baucom 	uint16_t			write_idx;
8788badb3aSMike Baucom 	uint16_t			bitlen;
8888badb3aSMike Baucom 	uint8_t				data[BNXT_ULP_FLMP_BLOB_SIZE];
8988badb3aSMike Baucom 	uint16_t			encap_swap_idx;
9088badb3aSMike Baucom };
9188badb3aSMike Baucom 
9288badb3aSMike Baucom /*
9388badb3aSMike Baucom  * The data can likely be only 32 bits for now.  Just size check
9488badb3aSMike Baucom  * the data when being written.
9588badb3aSMike Baucom  */
9688badb3aSMike Baucom #define ULP_REGFILE_ENTRY_SIZE	(sizeof(uint32_t))
9788badb3aSMike Baucom struct ulp_regfile_entry {
9888badb3aSMike Baucom 	uint64_t	data;
9988badb3aSMike Baucom 	uint32_t	size;
10088badb3aSMike Baucom };
10188badb3aSMike Baucom 
10288badb3aSMike Baucom struct ulp_regfile {
103a2417601SKishore Padmanabha 	struct ulp_regfile_entry entry[BNXT_ULP_RF_IDX_LAST];
10488badb3aSMike Baucom };
10588badb3aSMike Baucom 
10688badb3aSMike Baucom /*
10788badb3aSMike Baucom  * Initialize the regfile structure for writing
10888badb3aSMike Baucom  *
10988badb3aSMike Baucom  * regfile [in] Ptr to a regfile instance
11088badb3aSMike Baucom  *
111c569279aSShuanglin Wang  * returns zero on success
11288badb3aSMike Baucom  */
113*0c036a14SPeter Spreadborough static inline int32_t
114*0c036a14SPeter Spreadborough ulp_regfile_init(struct ulp_regfile *regfile)
115*0c036a14SPeter Spreadborough {
116*0c036a14SPeter Spreadborough 	/* validate the arguments */
117*0c036a14SPeter Spreadborough 	if (!regfile) {
118*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
119*0c036a14SPeter Spreadborough 		return -EINVAL;
120*0c036a14SPeter Spreadborough 	}
121*0c036a14SPeter Spreadborough 	memset(regfile, 0, sizeof(struct ulp_regfile));
122*0c036a14SPeter Spreadborough 	return 0; /* Success */
123*0c036a14SPeter Spreadborough }
12488badb3aSMike Baucom 
12588badb3aSMike Baucom /*
12688badb3aSMike Baucom  * Read a value from the regfile
12788badb3aSMike Baucom  *
12888badb3aSMike Baucom  * regfile [in] The regfile instance. Must be initialized prior to being used
12988badb3aSMike Baucom  *
13088badb3aSMike Baucom  * field [in] The field to be read within the regfile.
13188badb3aSMike Baucom  *
132*0c036a14SPeter Spreadborough  * data [in/out]
133*0c036a14SPeter Spreadborough  *
134c569279aSShuanglin Wang  * returns zero on success
13588badb3aSMike Baucom  */
136*0c036a14SPeter Spreadborough static inline int32_t
13788badb3aSMike Baucom ulp_regfile_read(struct ulp_regfile *regfile,
138a2417601SKishore Padmanabha 		 enum bnxt_ulp_rf_idx field,
139*0c036a14SPeter Spreadborough 		 uint64_t *data)
140*0c036a14SPeter Spreadborough {
141*0c036a14SPeter Spreadborough 	/* validate the arguments */
142*0c036a14SPeter Spreadborough 	if (unlikely(!regfile || field >= BNXT_ULP_RF_IDX_LAST)) {
143*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
144*0c036a14SPeter Spreadborough 		return -EINVAL;
145*0c036a14SPeter Spreadborough 	}
146*0c036a14SPeter Spreadborough 
147*0c036a14SPeter Spreadborough 	*data = regfile->entry[field].data;
148*0c036a14SPeter Spreadborough 	return 0;
149*0c036a14SPeter Spreadborough }
15088badb3aSMike Baucom 
15188badb3aSMike Baucom /*
15288badb3aSMike Baucom  * Write a value to the regfile
15388badb3aSMike Baucom  *
15488badb3aSMike Baucom  * regfile [in] The regfile instance.  Must be initialized prior to being used
15588badb3aSMike Baucom  *
15688badb3aSMike Baucom  * field [in] The field to be written within the regfile.
15788badb3aSMike Baucom  *
15888badb3aSMike Baucom  * data [in] The value is written into this variable.  It is going to be in the
15988badb3aSMike Baucom  * same byte order as it was written.
16088badb3aSMike Baucom  *
161*0c036a14SPeter Spreadborough  * size [in] The size in bytes of the value being written into this
162*0c036a14SPeter Spreadborough  * variable.
163*0c036a14SPeter Spreadborough  *
164*0c036a14SPeter Spreadborough  * returns 0 on success
16588badb3aSMike Baucom  */
166*0c036a14SPeter Spreadborough static inline int32_t
16788badb3aSMike Baucom ulp_regfile_write(struct ulp_regfile *regfile,
168a2417601SKishore Padmanabha 		  enum bnxt_ulp_rf_idx field,
169*0c036a14SPeter Spreadborough 		  uint64_t data)
170*0c036a14SPeter Spreadborough {
171*0c036a14SPeter Spreadborough 	/* validate the arguments */
172*0c036a14SPeter Spreadborough 	if (unlikely(!regfile || field >= BNXT_ULP_RF_IDX_LAST)) {
173*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
174*0c036a14SPeter Spreadborough 		return -EINVAL; /* failure */
175*0c036a14SPeter Spreadborough 	}
176*0c036a14SPeter Spreadborough 
177*0c036a14SPeter Spreadborough 	regfile->entry[field].data = data;
178*0c036a14SPeter Spreadborough 	return 0; /* Success */
179*0c036a14SPeter Spreadborough }
180*0c036a14SPeter Spreadborough 
181*0c036a14SPeter Spreadborough 
182*0c036a14SPeter Spreadborough /*
183*0c036a14SPeter Spreadborough  * Add data to the byte array in Big endian format.
184*0c036a14SPeter Spreadborough  *
185*0c036a14SPeter Spreadborough  * bs [in] The byte array where data is pushed
186*0c036a14SPeter Spreadborough  *
187*0c036a14SPeter Spreadborough  * bitpos [in] The offset where data is pushed
188*0c036a14SPeter Spreadborough  *
189*0c036a14SPeter Spreadborough  * bitlen [in] The number of bits to be added to the data array.
190*0c036a14SPeter Spreadborough  *
191*0c036a14SPeter Spreadborough  * val [in] The data to be added to the data array.
192*0c036a14SPeter Spreadborough  *
193*0c036a14SPeter Spreadborough  */
194*0c036a14SPeter Spreadborough static inline void
195*0c036a14SPeter Spreadborough ulp_bs_put_msb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
196*0c036a14SPeter Spreadborough {
197*0c036a14SPeter Spreadborough 	uint8_t bitoffs = bitpos % 8;
198*0c036a14SPeter Spreadborough 	uint16_t index  = bitpos / 8;
199*0c036a14SPeter Spreadborough 	uint8_t mask;
200*0c036a14SPeter Spreadborough 	uint8_t tmp;
201*0c036a14SPeter Spreadborough 	int8_t shift;
202*0c036a14SPeter Spreadborough 
203*0c036a14SPeter Spreadborough 	tmp = bs[index];
204*0c036a14SPeter Spreadborough 	mask = ((uint8_t)-1 >> (8 - bitlen));
205*0c036a14SPeter Spreadborough 	shift = 8 - bitoffs - bitlen;
206*0c036a14SPeter Spreadborough 	val &= mask;
207*0c036a14SPeter Spreadborough 
208*0c036a14SPeter Spreadborough 	if (shift >= 0) {
209*0c036a14SPeter Spreadborough 		tmp &= ~(mask << shift);
210*0c036a14SPeter Spreadborough 		tmp |= val << shift;
211*0c036a14SPeter Spreadborough 		bs[index] = tmp;
212*0c036a14SPeter Spreadborough 	} else {
213*0c036a14SPeter Spreadborough 		tmp &= ~((uint8_t)-1 >> bitoffs);
214*0c036a14SPeter Spreadborough 		tmp |= val >> -shift;
215*0c036a14SPeter Spreadborough 		bs[index++] = tmp;
216*0c036a14SPeter Spreadborough 
217*0c036a14SPeter Spreadborough 		tmp = bs[index];
218*0c036a14SPeter Spreadborough 		tmp &= ((uint8_t)-1 >> (bitlen - (8 - bitoffs)));
219*0c036a14SPeter Spreadborough 		tmp |= val << (8 + shift);
220*0c036a14SPeter Spreadborough 		bs[index] = tmp;
221*0c036a14SPeter Spreadborough 	}
222*0c036a14SPeter Spreadborough }
223*0c036a14SPeter Spreadborough 
224*0c036a14SPeter Spreadborough /*
225*0c036a14SPeter Spreadborough  * Add data to the byte array in Little endian format.
226*0c036a14SPeter Spreadborough  *
227*0c036a14SPeter Spreadborough  * bs [in] The byte array where data is pushed
228*0c036a14SPeter Spreadborough  *
229*0c036a14SPeter Spreadborough  * bitpos [in] The offset where data is pushed
230*0c036a14SPeter Spreadborough  *
231*0c036a14SPeter Spreadborough  * bitlen [in] The number of bits to be added to the data array.
232*0c036a14SPeter Spreadborough  *
233*0c036a14SPeter Spreadborough  * val [in] The data to be added to the data array.
234*0c036a14SPeter Spreadborough  *
235*0c036a14SPeter Spreadborough  */
236*0c036a14SPeter Spreadborough static inline void
237*0c036a14SPeter Spreadborough ulp_bs_put_lsb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
238*0c036a14SPeter Spreadborough {
239*0c036a14SPeter Spreadborough 	uint8_t bitoffs = bitpos % 8;
240*0c036a14SPeter Spreadborough 	uint16_t index  = bitpos / 8;
241*0c036a14SPeter Spreadborough 	uint8_t mask;
242*0c036a14SPeter Spreadborough 	uint8_t tmp;
243*0c036a14SPeter Spreadborough 	uint8_t shift;
244*0c036a14SPeter Spreadborough 	uint8_t partial;
245*0c036a14SPeter Spreadborough 
246*0c036a14SPeter Spreadborough 	tmp = bs[index];
247*0c036a14SPeter Spreadborough 	shift = bitoffs;
248*0c036a14SPeter Spreadborough 
249*0c036a14SPeter Spreadborough 	if (bitoffs + bitlen <= 8) {
250*0c036a14SPeter Spreadborough 		mask = ((1 << bitlen) - 1) << shift;
251*0c036a14SPeter Spreadborough 		tmp &= ~mask;
252*0c036a14SPeter Spreadborough 		tmp |= ((val << shift) & mask);
253*0c036a14SPeter Spreadborough 		bs[index] = tmp;
254*0c036a14SPeter Spreadborough 	} else {
255*0c036a14SPeter Spreadborough 		partial = 8 - bitoffs;
256*0c036a14SPeter Spreadborough 		mask = ((1 << partial) - 1) << shift;
257*0c036a14SPeter Spreadborough 		tmp &= ~mask;
258*0c036a14SPeter Spreadborough 		tmp |= ((val << shift) & mask);
259*0c036a14SPeter Spreadborough 		bs[index++] = tmp;
260*0c036a14SPeter Spreadborough 
261*0c036a14SPeter Spreadborough 		val >>= partial;
262*0c036a14SPeter Spreadborough 		partial = bitlen - partial;
263*0c036a14SPeter Spreadborough 		mask = ((1 << partial) - 1);
264*0c036a14SPeter Spreadborough 		tmp = bs[index];
265*0c036a14SPeter Spreadborough 		tmp &= ~mask;
266*0c036a14SPeter Spreadborough 		tmp |= (val & mask);
267*0c036a14SPeter Spreadborough 		bs[index] = tmp;
268*0c036a14SPeter Spreadborough 	}
269*0c036a14SPeter Spreadborough }
27088badb3aSMike Baucom 
27188badb3aSMike Baucom /*
272f634204bSKishore Padmanabha  * Add data to the byte array in Little endian format.
273f634204bSKishore Padmanabha  *
274f634204bSKishore Padmanabha  * bs [in] The byte array where data is pushed
275f634204bSKishore Padmanabha  *
276f634204bSKishore Padmanabha  * pos [in] The offset where data is pushed
277f634204bSKishore Padmanabha  *
278f634204bSKishore Padmanabha  * len [in] The number of bits to be added to the data array.
279f634204bSKishore Padmanabha  *
280f634204bSKishore Padmanabha  * val [in] The data to be added to the data array.
281f634204bSKishore Padmanabha  *
282f634204bSKishore Padmanabha  * returns the number of bits pushed.
283f634204bSKishore Padmanabha  */
284*0c036a14SPeter Spreadborough static inline uint32_t
285*0c036a14SPeter Spreadborough ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
286*0c036a14SPeter Spreadborough {
287*0c036a14SPeter Spreadborough 	int i;
288*0c036a14SPeter Spreadborough 	int cnt = (len) / 8;
289*0c036a14SPeter Spreadborough 	int tlen = len;
290*0c036a14SPeter Spreadborough 
291*0c036a14SPeter Spreadborough 	if (cnt > 0 && !(len % 8))
292*0c036a14SPeter Spreadborough 		cnt -= 1;
293*0c036a14SPeter Spreadborough 
294*0c036a14SPeter Spreadborough 	for (i = 0; i < cnt; i++) {
295*0c036a14SPeter Spreadborough 		ulp_bs_put_lsb(bs, pos, 8, val[cnt - i]);
296*0c036a14SPeter Spreadborough 		pos += 8;
297*0c036a14SPeter Spreadborough 		tlen -= 8;
298*0c036a14SPeter Spreadborough 	}
299*0c036a14SPeter Spreadborough 
300*0c036a14SPeter Spreadborough 	/* Handle the remainder bits */
301*0c036a14SPeter Spreadborough 	if (tlen)
302*0c036a14SPeter Spreadborough 		ulp_bs_put_lsb(bs, pos, tlen, val[0]);
303*0c036a14SPeter Spreadborough 	return len;
304*0c036a14SPeter Spreadborough }
305f634204bSKishore Padmanabha 
306f634204bSKishore Padmanabha /*
307f634204bSKishore Padmanabha  * Add data to the byte array in Big endian format.
308f634204bSKishore Padmanabha  *
309f634204bSKishore Padmanabha  * bs [in] The byte array where data is pushed
310f634204bSKishore Padmanabha  *
311f634204bSKishore Padmanabha  * pos [in] The offset where data is pushed
312f634204bSKishore Padmanabha  *
313f634204bSKishore Padmanabha  * len [in] The number of bits to be added to the data array.
314f634204bSKishore Padmanabha  *
315f634204bSKishore Padmanabha  * val [in] The data to be added to the data array.
316f634204bSKishore Padmanabha  *
317f634204bSKishore Padmanabha  * returns the number of bits pushed.
318f634204bSKishore Padmanabha  */
319*0c036a14SPeter Spreadborough static inline uint32_t
320*0c036a14SPeter Spreadborough ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
321*0c036a14SPeter Spreadborough {
322*0c036a14SPeter Spreadborough 	int i;
323*0c036a14SPeter Spreadborough 	int cnt = (len + 7) / 8;
324*0c036a14SPeter Spreadborough 
325*0c036a14SPeter Spreadborough 	/* Handle any remainder bits */
326*0c036a14SPeter Spreadborough 	int tmp = len % 8;
327*0c036a14SPeter Spreadborough 
328*0c036a14SPeter Spreadborough 	if (!tmp)
329*0c036a14SPeter Spreadborough 		tmp = 8;
330*0c036a14SPeter Spreadborough 
331*0c036a14SPeter Spreadborough 	ulp_bs_put_msb(bs, pos, tmp, val[0]);
332*0c036a14SPeter Spreadborough 
333*0c036a14SPeter Spreadborough 	pos += tmp;
334*0c036a14SPeter Spreadborough 
335*0c036a14SPeter Spreadborough 	for (i = 1; i < cnt; i++) {
336*0c036a14SPeter Spreadborough 		ulp_bs_put_msb(bs, pos, 8, val[i]);
337*0c036a14SPeter Spreadborough 		pos += 8;
338*0c036a14SPeter Spreadborough 	}
339*0c036a14SPeter Spreadborough 
340*0c036a14SPeter Spreadborough 	return len;
341*0c036a14SPeter Spreadborough }
342f634204bSKishore Padmanabha 
343f634204bSKishore Padmanabha /*
34488badb3aSMike Baucom  * Initializes the blob structure for creating binary blob
34588badb3aSMike Baucom  *
34688badb3aSMike Baucom  * blob [in] The blob to be initialized
34788badb3aSMike Baucom  *
34888badb3aSMike Baucom  * bitlen [in] The bit length of the blob
34988badb3aSMike Baucom  *
35088badb3aSMike Baucom  * order [in] The byte order for the blob.  Currently only supporting
35188badb3aSMike Baucom  * big endian.  All fields are packed with this order.
35288badb3aSMike Baucom  *
353c569279aSShuanglin Wang  * returns zero on success
354*0c036a14SPeter Spreadborough  * Notes - If bitlen is zero then set it to max.
35588badb3aSMike Baucom  */
356*0c036a14SPeter Spreadborough static inline int32_t
35788badb3aSMike Baucom ulp_blob_init(struct ulp_blob *blob,
35888badb3aSMike Baucom 	      uint16_t bitlen,
359*0c036a14SPeter Spreadborough 	      enum bnxt_ulp_byte_order order)
360*0c036a14SPeter Spreadborough {
361*0c036a14SPeter Spreadborough 	/* validate the arguments */
362*0c036a14SPeter Spreadborough 	if (unlikely(!blob || bitlen > (8 * sizeof(blob->data)))) {
363*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
364*0c036a14SPeter Spreadborough 		return -EINVAL;
365*0c036a14SPeter Spreadborough 	}
366*0c036a14SPeter Spreadborough 	if (bitlen)
367*0c036a14SPeter Spreadborough 		blob->bitlen = bitlen;
368*0c036a14SPeter Spreadborough 	else
369*0c036a14SPeter Spreadborough 		blob->bitlen = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
370*0c036a14SPeter Spreadborough 	blob->byte_order = order;
371*0c036a14SPeter Spreadborough 	blob->write_idx = 0;
372*0c036a14SPeter Spreadborough 	memset(blob->data, 0, sizeof(blob->data));
373*0c036a14SPeter Spreadborough 	return 0; /* Success */
374*0c036a14SPeter Spreadborough }
37588badb3aSMike Baucom 
37688badb3aSMike Baucom /*
37788badb3aSMike Baucom  * Add data to the binary blob at the current offset.
37888badb3aSMike Baucom  *
37988badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
38088badb3aSMike Baucom  * be initialized prior to pushing data.
38188badb3aSMike Baucom  *
38288badb3aSMike Baucom  * data [in] A pointer to bytes to be added to the blob.
38388badb3aSMike Baucom  *
38488badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
38588badb3aSMike Baucom  *
38688badb3aSMike Baucom  * The offset of the data is updated after each push of data.
387c569279aSShuanglin Wang  *
388c569279aSShuanglin Wang  * returns zero on success
38988badb3aSMike Baucom  */
390*0c036a14SPeter Spreadborough #define ULP_BLOB_BYTE		8
391*0c036a14SPeter Spreadborough #define ULP_BLOB_BYTE_HEX	0xFF
392*0c036a14SPeter Spreadborough #define BLOB_MASK_CAL(x)	((0xFF << (x)) & 0xFF)
393*0c036a14SPeter Spreadborough static inline int32_t
39488badb3aSMike Baucom ulp_blob_push(struct ulp_blob *blob,
39588badb3aSMike Baucom 	      uint8_t *data,
396*0c036a14SPeter Spreadborough 	      uint32_t datalen)
397*0c036a14SPeter Spreadborough {
398*0c036a14SPeter Spreadborough 	uint32_t rc;
399*0c036a14SPeter Spreadborough 
400*0c036a14SPeter Spreadborough 	/* validate the arguments */
401*0c036a14SPeter Spreadborough 	if (unlikely(!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx))) {
402*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
403*0c036a14SPeter Spreadborough 		return -EINVAL;
404*0c036a14SPeter Spreadborough 	}
405*0c036a14SPeter Spreadborough 
406*0c036a14SPeter Spreadborough 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
407*0c036a14SPeter Spreadborough 		rc = ulp_bs_push_msb(blob->data,
408*0c036a14SPeter Spreadborough 				     blob->write_idx,
409*0c036a14SPeter Spreadborough 				     datalen,
410*0c036a14SPeter Spreadborough 				     data);
411*0c036a14SPeter Spreadborough 	else
412*0c036a14SPeter Spreadborough 		rc = ulp_bs_push_lsb(blob->data,
413*0c036a14SPeter Spreadborough 				     blob->write_idx,
414*0c036a14SPeter Spreadborough 				     datalen,
415*0c036a14SPeter Spreadborough 				     data);
416*0c036a14SPeter Spreadborough 	if (unlikely(!rc)) {
417*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "Failed to write blob\n");
418*0c036a14SPeter Spreadborough 		return -EINVAL;
419*0c036a14SPeter Spreadborough 	}
420*0c036a14SPeter Spreadborough 	blob->write_idx += datalen;
421*0c036a14SPeter Spreadborough 	return 0;
422*0c036a14SPeter Spreadborough }
42388badb3aSMike Baucom 
42488badb3aSMike Baucom /*
4257e604e7fSKishore Padmanabha  * Insert data into the binary blob at the given offset.
4267e604e7fSKishore Padmanabha  *
4277e604e7fSKishore Padmanabha  * blob [in] The blob that data is added to.  The blob must
4287e604e7fSKishore Padmanabha  * be initialized prior to pushing data.
4297e604e7fSKishore Padmanabha  *
4307e604e7fSKishore Padmanabha  * offset [in] The offset where the data needs to be inserted.
4317e604e7fSKishore Padmanabha  *
4327e604e7fSKishore Padmanabha  * data [in/out] A pointer to bytes to be added to the blob.
4337e604e7fSKishore Padmanabha  *
4347e604e7fSKishore Padmanabha  * datalen [in] The number of bits to be added to the blob.
4357e604e7fSKishore Padmanabha  *
4367e604e7fSKishore Padmanabha  * The offset of the data is updated after each push of data.
437c569279aSShuanglin Wang  *
438c569279aSShuanglin Wang  * returns zero on success
4397e604e7fSKishore Padmanabha  */
440*0c036a14SPeter Spreadborough static inline int32_t
4417e604e7fSKishore Padmanabha ulp_blob_insert(struct ulp_blob *blob, uint32_t offset,
442*0c036a14SPeter Spreadborough 		uint8_t *data, uint32_t datalen)
443*0c036a14SPeter Spreadborough {
444*0c036a14SPeter Spreadborough 	uint32_t rc;
445*0c036a14SPeter Spreadborough 	uint8_t local_data[BNXT_ULP_FLMP_BLOB_SIZE];
446*0c036a14SPeter Spreadborough 	uint16_t mov_len;
447*0c036a14SPeter Spreadborough 
448*0c036a14SPeter Spreadborough 	/* validate the arguments */
449*0c036a14SPeter Spreadborough 	if (unlikely(!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx) ||
450*0c036a14SPeter Spreadborough 		     offset > blob->write_idx)) {
451*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
452*0c036a14SPeter Spreadborough 		return -EINVAL;
453*0c036a14SPeter Spreadborough 	}
454*0c036a14SPeter Spreadborough 
455*0c036a14SPeter Spreadborough 	mov_len = blob->write_idx - offset;
456*0c036a14SPeter Spreadborough 	/* If offset and data len are not 8 bit aligned then return error */
457*0c036a14SPeter Spreadborough 	if (unlikely(ULP_BITS_IS_BYTE_NOT_ALIGNED(offset) ||
458*0c036a14SPeter Spreadborough 		     ULP_BITS_IS_BYTE_NOT_ALIGNED(datalen))) {
459*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument, not aligned\n");
460*0c036a14SPeter Spreadborough 		return -EINVAL;
461*0c036a14SPeter Spreadborough 	}
462*0c036a14SPeter Spreadborough 
463*0c036a14SPeter Spreadborough 	/* copy the data so we can move the data */
464*0c036a14SPeter Spreadborough 	memcpy(local_data, &blob->data[ULP_BITS_2_BYTE_NR(offset)],
465*0c036a14SPeter Spreadborough 	       ULP_BITS_2_BYTE(mov_len));
466*0c036a14SPeter Spreadborough 	blob->write_idx = offset;
467*0c036a14SPeter Spreadborough 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
468*0c036a14SPeter Spreadborough 		rc = ulp_bs_push_msb(blob->data,
469*0c036a14SPeter Spreadborough 				     blob->write_idx,
470*0c036a14SPeter Spreadborough 				     datalen,
471*0c036a14SPeter Spreadborough 				     data);
472*0c036a14SPeter Spreadborough 	else
473*0c036a14SPeter Spreadborough 		rc = ulp_bs_push_lsb(blob->data,
474*0c036a14SPeter Spreadborough 				     blob->write_idx,
475*0c036a14SPeter Spreadborough 				     datalen,
476*0c036a14SPeter Spreadborough 				     data);
477*0c036a14SPeter Spreadborough 	if (unlikely(!rc)) {
478*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "Failed to write blob\n");
479*0c036a14SPeter Spreadborough 		return -EINVAL;
480*0c036a14SPeter Spreadborough 	}
481*0c036a14SPeter Spreadborough 	/* copy the previously stored data */
482*0c036a14SPeter Spreadborough 	memcpy(&blob->data[ULP_BITS_2_BYTE_NR(offset + datalen)], local_data,
483*0c036a14SPeter Spreadborough 	       ULP_BITS_2_BYTE(mov_len));
484*0c036a14SPeter Spreadborough 	blob->write_idx += (mov_len + datalen);
485*0c036a14SPeter Spreadborough 	return 0;
486*0c036a14SPeter Spreadborough }
4877e604e7fSKishore Padmanabha 
4887e604e7fSKishore Padmanabha /*
48988badb3aSMike Baucom  * Add data to the binary blob at the current offset.
49088badb3aSMike Baucom  *
49188badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
49288badb3aSMike Baucom  * be initialized prior to pushing data.
49388badb3aSMike Baucom  *
49488badb3aSMike Baucom  * data [in] 64-bit value to be added to the blob.
49588badb3aSMike Baucom  *
49688badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
49788badb3aSMike Baucom  *
49888badb3aSMike Baucom  * The offset of the data is updated after each push of data.
499*0c036a14SPeter Spreadborough  * NULL returned on error, pointer pushed value otherwise.
50088badb3aSMike Baucom  */
501*0c036a14SPeter Spreadborough static inline uint8_t *
50288badb3aSMike Baucom ulp_blob_push_64(struct ulp_blob *blob,
50388badb3aSMike Baucom 		 uint64_t *data,
504*0c036a14SPeter Spreadborough 		 uint32_t datalen)
505*0c036a14SPeter Spreadborough {
506*0c036a14SPeter Spreadborough 	uint8_t *val = (uint8_t *)data;
507*0c036a14SPeter Spreadborough 	int rc;
508*0c036a14SPeter Spreadborough 
509*0c036a14SPeter Spreadborough 	int size = (datalen + 7) / 8;
510*0c036a14SPeter Spreadborough 
511*0c036a14SPeter Spreadborough 	if (unlikely(!blob || !data ||
512*0c036a14SPeter Spreadborough 		     datalen > (uint32_t)(blob->bitlen - blob->write_idx))) {
513*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
514*0c036a14SPeter Spreadborough 		return NULL;
515*0c036a14SPeter Spreadborough 	}
516*0c036a14SPeter Spreadborough 
517*0c036a14SPeter Spreadborough 	rc = ulp_blob_push(blob, &val[8 - size], datalen);
518*0c036a14SPeter Spreadborough 	if (unlikely(rc))
519*0c036a14SPeter Spreadborough 		return NULL;
520*0c036a14SPeter Spreadborough 
521*0c036a14SPeter Spreadborough 	return &val[8 - size];
522*0c036a14SPeter Spreadborough }
52388badb3aSMike Baucom 
52488badb3aSMike Baucom /*
525a2be13e1SKishore Padmanabha  * Add data to the binary blob at the current offset.
526a2be13e1SKishore Padmanabha  *
527a2be13e1SKishore Padmanabha  * blob [in] The blob that data is added to.  The blob must
528a2be13e1SKishore Padmanabha  * be initialized prior to pushing data.
529a2be13e1SKishore Padmanabha  *
530a2be13e1SKishore Padmanabha  * data [in] 32-bit value to be added to the blob.
531a2be13e1SKishore Padmanabha  *
532*0c036a14SPeter Spreadborough  * datalen [in] The number of bits to be added to the blob.
533a2be13e1SKishore Padmanabha  *
534a2be13e1SKishore Padmanabha  * The offset of the data is updated after each push of data.
535a2be13e1SKishore Padmanabha  * NULL returned on error, pointer pushed value otherwise.
536a2be13e1SKishore Padmanabha  */
537*0c036a14SPeter Spreadborough static inline uint8_t *
538a2be13e1SKishore Padmanabha ulp_blob_push_32(struct ulp_blob *blob,
539a2be13e1SKishore Padmanabha 		 uint32_t *data,
540*0c036a14SPeter Spreadborough 		 uint32_t datalen)
541*0c036a14SPeter Spreadborough {
542*0c036a14SPeter Spreadborough 	uint8_t *val = (uint8_t *)data;
543*0c036a14SPeter Spreadborough 	uint32_t rc;
544*0c036a14SPeter Spreadborough 	uint32_t size = ULP_BITS_2_BYTE(datalen);
545*0c036a14SPeter Spreadborough 
546*0c036a14SPeter Spreadborough 	if (unlikely(!data || size > sizeof(uint32_t))) {
547*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
548*0c036a14SPeter Spreadborough 		return NULL;
549*0c036a14SPeter Spreadborough 	}
550*0c036a14SPeter Spreadborough 
551*0c036a14SPeter Spreadborough 	rc = ulp_blob_push(blob, &val[sizeof(uint32_t) - size], datalen);
552*0c036a14SPeter Spreadborough 	if (unlikely(rc))
553*0c036a14SPeter Spreadborough 		return NULL;
554*0c036a14SPeter Spreadborough 
555*0c036a14SPeter Spreadborough 	return &val[sizeof(uint32_t) - size];
556*0c036a14SPeter Spreadborough }
557a2be13e1SKishore Padmanabha 
558a2be13e1SKishore Padmanabha /*
55988badb3aSMike Baucom  * Add encap data to the binary blob at the current offset.
56088badb3aSMike Baucom  *
56188badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
56288badb3aSMike Baucom  * be initialized prior to pushing data.
56388badb3aSMike Baucom  *
56488badb3aSMike Baucom  * data [in] value to be added to the blob.
56588badb3aSMike Baucom  *
56688badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
56788badb3aSMike Baucom  *
56888badb3aSMike Baucom  * The offset of the data is updated after each push of data.
56988badb3aSMike Baucom  * NULL returned on error, pointer pushed value otherwise.
57088badb3aSMike Baucom  */
571*0c036a14SPeter Spreadborough static inline int32_t
57288badb3aSMike Baucom ulp_blob_push_encap(struct ulp_blob *blob,
57388badb3aSMike Baucom 		    uint8_t *data,
574*0c036a14SPeter Spreadborough 		    uint32_t datalen)
575*0c036a14SPeter Spreadborough {
576*0c036a14SPeter Spreadborough 	uint8_t		*val = (uint8_t *)data;
577*0c036a14SPeter Spreadborough 	uint32_t	initial_size, write_size = datalen;
578*0c036a14SPeter Spreadborough 	uint32_t	size = 0;
579*0c036a14SPeter Spreadborough 
580*0c036a14SPeter Spreadborough 	if (unlikely(!blob || !data ||
581*0c036a14SPeter Spreadborough 		     datalen > (uint32_t)(blob->bitlen - blob->write_idx))) {
582*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
583*0c036a14SPeter Spreadborough 		return -1;
584*0c036a14SPeter Spreadborough 	}
585*0c036a14SPeter Spreadborough 
586*0c036a14SPeter Spreadborough 	initial_size = ULP_BYTE_2_BITS(sizeof(uint64_t)) -
587*0c036a14SPeter Spreadborough 	    (blob->write_idx % ULP_BYTE_2_BITS(sizeof(uint64_t)));
588*0c036a14SPeter Spreadborough 	while (write_size > 0) {
589*0c036a14SPeter Spreadborough 		if (initial_size && write_size > initial_size) {
590*0c036a14SPeter Spreadborough 			size = initial_size;
591*0c036a14SPeter Spreadborough 			initial_size = 0;
592*0c036a14SPeter Spreadborough 		} else if (initial_size && write_size <= initial_size) {
593*0c036a14SPeter Spreadborough 			size = write_size;
594*0c036a14SPeter Spreadborough 			initial_size = 0;
595*0c036a14SPeter Spreadborough 		} else if (write_size > ULP_BYTE_2_BITS(sizeof(uint64_t))) {
596*0c036a14SPeter Spreadborough 			size = ULP_BYTE_2_BITS(sizeof(uint64_t));
597*0c036a14SPeter Spreadborough 		} else {
598*0c036a14SPeter Spreadborough 			size = write_size;
599*0c036a14SPeter Spreadborough 		}
600*0c036a14SPeter Spreadborough 		if (unlikely(ulp_blob_push(blob, val, size))) {
601*0c036a14SPeter Spreadborough 			BNXT_DRV_DBG(ERR, "push field failed\n");
602*0c036a14SPeter Spreadborough 			return -1;
603*0c036a14SPeter Spreadborough 		}
604*0c036a14SPeter Spreadborough 		val += ULP_BITS_2_BYTE(size);
605*0c036a14SPeter Spreadborough 		write_size -= size;
606*0c036a14SPeter Spreadborough 	}
607*0c036a14SPeter Spreadborough 	return datalen;
608*0c036a14SPeter Spreadborough }
60988badb3aSMike Baucom 
61088badb3aSMike Baucom /*
611*0c036a14SPeter Spreadborough  * Adds pad to an initialized blob at the current offset
61288badb3aSMike Baucom  *
613*0c036a14SPeter Spreadborough  * blob [in] The blob that data is added to.  The blob must
614*0c036a14SPeter Spreadborough  * be initialized prior to pushing data.
61588badb3aSMike Baucom  *
616*0c036a14SPeter Spreadborough  * datalen [in] The number of bits of pad to add
61788badb3aSMike Baucom  *
618*0c036a14SPeter Spreadborough  * returns the number of pad bits added, -1 on failure
61988badb3aSMike Baucom  */
620*0c036a14SPeter Spreadborough static inline int32_t
621*0c036a14SPeter Spreadborough ulp_blob_pad_push(struct ulp_blob *blob,
622*0c036a14SPeter Spreadborough 		  uint32_t datalen)
623*0c036a14SPeter Spreadborough {
624*0c036a14SPeter Spreadborough 	if (unlikely(datalen > (uint32_t)(blob->bitlen - blob->write_idx))) {
625*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "Pad too large for blob\n");
626*0c036a14SPeter Spreadborough 		return -1;
627*0c036a14SPeter Spreadborough 	}
628*0c036a14SPeter Spreadborough 
629*0c036a14SPeter Spreadborough 	blob->write_idx += datalen;
630*0c036a14SPeter Spreadborough 	return datalen;
631*0c036a14SPeter Spreadborough }
63288badb3aSMike Baucom 
63388badb3aSMike Baucom /*
634*0c036a14SPeter Spreadborough  * Adds pad to an initialized blob at the current offset based on
635*0c036a14SPeter Spreadborough  * the alignment.
6363fe124d2SKishore Padmanabha  *
637*0c036a14SPeter Spreadborough  * blob [in] The blob that needs to be aligned
6383fe124d2SKishore Padmanabha  *
639*0c036a14SPeter Spreadborough  * align [in] Alignment in bits.
640*0c036a14SPeter Spreadborough  *
641*0c036a14SPeter Spreadborough  * returns the number of pad bits added, -1 on failure
6423fe124d2SKishore Padmanabha  */
643*0c036a14SPeter Spreadborough static inline int32_t
644*0c036a14SPeter Spreadborough ulp_blob_pad_align(struct ulp_blob *blob,
645*0c036a14SPeter Spreadborough 		   uint32_t align)
646*0c036a14SPeter Spreadborough {
647*0c036a14SPeter Spreadborough 	int32_t pad = 0;
648*0c036a14SPeter Spreadborough 
649*0c036a14SPeter Spreadborough 	pad = RTE_ALIGN(blob->write_idx, align) - blob->write_idx;
650*0c036a14SPeter Spreadborough 	if (unlikely(pad > (int32_t)(blob->bitlen - blob->write_idx))) {
651*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "Pad too large for blob\n");
652*0c036a14SPeter Spreadborough 		return -1;
653*0c036a14SPeter Spreadborough 	}
654*0c036a14SPeter Spreadborough 	blob->write_idx += pad;
655*0c036a14SPeter Spreadborough 	return pad;
656*0c036a14SPeter Spreadborough }
657*0c036a14SPeter Spreadborough 
658*0c036a14SPeter Spreadborough /* Get data from src and put into dst using little-endian format */
659*0c036a14SPeter Spreadborough static inline void
660*0c036a14SPeter Spreadborough ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
661*0c036a14SPeter Spreadborough {
662*0c036a14SPeter Spreadborough 	uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
663*0c036a14SPeter Spreadborough 	uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
664*0c036a14SPeter Spreadborough 	uint8_t mask, partial, shift;
665*0c036a14SPeter Spreadborough 
666*0c036a14SPeter Spreadborough 	shift = bitoffs;
667*0c036a14SPeter Spreadborough 	partial = ULP_BLOB_BYTE - bitoffs;
668*0c036a14SPeter Spreadborough 	if (bitoffs + bitlen <= ULP_BLOB_BYTE) {
669*0c036a14SPeter Spreadborough 		mask = ((1 << bitlen) - 1) << shift;
670*0c036a14SPeter Spreadborough 		*dst = (src[index] & mask) >> shift;
671*0c036a14SPeter Spreadborough 	} else {
672*0c036a14SPeter Spreadborough 		mask = ((1 << partial) - 1) << shift;
673*0c036a14SPeter Spreadborough 		*dst = (src[index] & mask) >> shift;
674*0c036a14SPeter Spreadborough 		index++;
675*0c036a14SPeter Spreadborough 		partial = bitlen - partial;
676*0c036a14SPeter Spreadborough 		mask = ((1 << partial) - 1);
677*0c036a14SPeter Spreadborough 		*dst |= (src[index] & mask) << (ULP_BLOB_BYTE - bitoffs);
678*0c036a14SPeter Spreadborough 	}
679*0c036a14SPeter Spreadborough }
6803fe124d2SKishore Padmanabha 
6813fe124d2SKishore Padmanabha /*
682f634204bSKishore Padmanabha  * Get data from the byte array in Little endian format.
683f634204bSKishore Padmanabha  *
684f634204bSKishore Padmanabha  * src [in] The byte array where data is extracted from
685f634204bSKishore Padmanabha  *
686f634204bSKishore Padmanabha  * dst [out] The byte array where data is pulled into
687f634204bSKishore Padmanabha  *
688f634204bSKishore Padmanabha  * size [in] The size of dst array in bytes
689f634204bSKishore Padmanabha  *
690f634204bSKishore Padmanabha  * offset [in] The offset where data is pulled
691f634204bSKishore Padmanabha  *
692f634204bSKishore Padmanabha  * len [in] The number of bits to be extracted from the data array
693f634204bSKishore Padmanabha  *
694f634204bSKishore Padmanabha  * returns None.
695f634204bSKishore Padmanabha  */
696*0c036a14SPeter Spreadborough static inline void
697f634204bSKishore Padmanabha ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size,
698*0c036a14SPeter Spreadborough 		uint32_t offset, uint32_t len)
699*0c036a14SPeter Spreadborough {
700*0c036a14SPeter Spreadborough 	uint32_t idx;
701*0c036a14SPeter Spreadborough 	uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
702*0c036a14SPeter Spreadborough 
703*0c036a14SPeter Spreadborough 	/* iterate bytewise to get data */
704*0c036a14SPeter Spreadborough 	for (idx = 0; idx < cnt; idx++) {
705*0c036a14SPeter Spreadborough 		ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE,
706*0c036a14SPeter Spreadborough 			       &dst[size - 1 - idx]);
707*0c036a14SPeter Spreadborough 		offset += ULP_BLOB_BYTE;
708*0c036a14SPeter Spreadborough 		len -= ULP_BLOB_BYTE;
709*0c036a14SPeter Spreadborough 	}
710*0c036a14SPeter Spreadborough 
711*0c036a14SPeter Spreadborough 	/* Extract the last reminder data that is not 8 byte boundary */
712*0c036a14SPeter Spreadborough 	if (len)
713*0c036a14SPeter Spreadborough 		ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]);
714*0c036a14SPeter Spreadborough }
715*0c036a14SPeter Spreadborough 
716*0c036a14SPeter Spreadborough /*
717*0c036a14SPeter Spreadborough  * Get data from the byte array in Big endian format.
718*0c036a14SPeter Spreadborough  *
719*0c036a14SPeter Spreadborough  * src [in] The byte array where data is extracted from
720*0c036a14SPeter Spreadborough  *
721*0c036a14SPeter Spreadborough  * bitpos [in] The offset where data is pulled
722*0c036a14SPeter Spreadborough  *
723*0c036a14SPeter Spreadborough  * bitlen [in] The number of bits to be extracted from the data array
724*0c036a14SPeter Spreadborough  *
725*0c036a14SPeter Spreadborough  * dst [out] The byte array where data is pulled into
726*0c036a14SPeter Spreadborough  *
727*0c036a14SPeter Spreadborough  * returns None.
728*0c036a14SPeter Spreadborough  */
729*0c036a14SPeter Spreadborough /* Get data from src and put into dst using big-endian format */
730*0c036a14SPeter Spreadborough static inline void
731*0c036a14SPeter Spreadborough ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
732*0c036a14SPeter Spreadborough {
733*0c036a14SPeter Spreadborough 	uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
734*0c036a14SPeter Spreadborough 	uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
735*0c036a14SPeter Spreadborough 	uint8_t mask;
736*0c036a14SPeter Spreadborough 	int32_t shift;
737*0c036a14SPeter Spreadborough 
738*0c036a14SPeter Spreadborough 	shift = ULP_BLOB_BYTE - bitoffs - bitlen;
739*0c036a14SPeter Spreadborough 	if (shift >= 0) {
740*0c036a14SPeter Spreadborough 		mask = 0xFF >> -bitlen;
741*0c036a14SPeter Spreadborough 		*dst = (src[index] >> shift) & mask;
742*0c036a14SPeter Spreadborough 	} else {
743*0c036a14SPeter Spreadborough 		*dst = (src[index] & (0xFF >> bitoffs)) << -shift;
744*0c036a14SPeter Spreadborough 		*dst |= src[index + 1] >> -shift;
745*0c036a14SPeter Spreadborough 	}
746*0c036a14SPeter Spreadborough }
747f634204bSKishore Padmanabha 
748f634204bSKishore Padmanabha /*
749f634204bSKishore Padmanabha  * Get data from the byte array in Big endian format.
750f634204bSKishore Padmanabha  *
751f634204bSKishore Padmanabha  * src [in] The byte array where data is extracted from
752f634204bSKishore Padmanabha  *
753f634204bSKishore Padmanabha  * dst [out] The byte array where data is pulled into
754f634204bSKishore Padmanabha  *
755f634204bSKishore Padmanabha  * offset [in] The offset where data is pulled
756f634204bSKishore Padmanabha  *
757f634204bSKishore Padmanabha  * len [in] The number of bits to be extracted from the data array
758f634204bSKishore Padmanabha  *
759f634204bSKishore Padmanabha  * returns None.
760f634204bSKishore Padmanabha  */
761*0c036a14SPeter Spreadborough static inline void
762f634204bSKishore Padmanabha ulp_bs_pull_msb(uint8_t *src, uint8_t *dst,
763*0c036a14SPeter Spreadborough 		uint32_t offset, uint32_t len)
764*0c036a14SPeter Spreadborough {
765*0c036a14SPeter Spreadborough 	uint32_t idx;
766*0c036a14SPeter Spreadborough 	uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
767*0c036a14SPeter Spreadborough 
768*0c036a14SPeter Spreadborough 	/* iterate bytewise to get data */
769*0c036a14SPeter Spreadborough 	for (idx = 0; idx < cnt; idx++) {
770*0c036a14SPeter Spreadborough 		ulp_bs_get_msb(src, offset, ULP_BLOB_BYTE, &dst[idx]);
771*0c036a14SPeter Spreadborough 		offset += ULP_BLOB_BYTE;
772*0c036a14SPeter Spreadborough 		len -= ULP_BLOB_BYTE;
773*0c036a14SPeter Spreadborough 	}
774*0c036a14SPeter Spreadborough 
775*0c036a14SPeter Spreadborough 	/* Extract the last reminder data that is not 8 byte boundary */
776*0c036a14SPeter Spreadborough 	if (len)
777*0c036a14SPeter Spreadborough 		ulp_bs_get_msb(src, offset, len, &dst[idx]);
778*0c036a14SPeter Spreadborough }
779f634204bSKishore Padmanabha 
780f634204bSKishore Padmanabha /*
781afd35335SKishore Padmanabha  * Extract data from the binary blob using given offset.
782afd35335SKishore Padmanabha  *
783afd35335SKishore Padmanabha  * blob [in] The blob that data is extracted from. The blob must
784afd35335SKishore Padmanabha  * be initialized prior to pulling data.
785afd35335SKishore Padmanabha  *
786afd35335SKishore Padmanabha  * data [in] A pointer to put the data.
787afd35335SKishore Padmanabha  * data_size [in] size of the data buffer in bytes.
788afd35335SKishore Padmanabha  *offset [in] - Offset in the blob to extract the data in bits format.
789afd35335SKishore Padmanabha  * len [in] The number of bits to be pulled from the blob.
790afd35335SKishore Padmanabha  *
791afd35335SKishore Padmanabha  * Output: zero on success, -1 on failure
792afd35335SKishore Padmanabha  */
793*0c036a14SPeter Spreadborough static inline int32_t
794afd35335SKishore Padmanabha ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size,
795*0c036a14SPeter Spreadborough 	      uint16_t offset, uint16_t len)
796*0c036a14SPeter Spreadborough {
797*0c036a14SPeter Spreadborough 	/* validate the arguments */
798*0c036a14SPeter Spreadborough 	if (unlikely(!blob || (offset + len) > blob->bitlen ||
799*0c036a14SPeter Spreadborough 		     ULP_BYTE_2_BITS(data_size) < len)) {
800*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
801*0c036a14SPeter Spreadborough 		return -1; /* failure */
802*0c036a14SPeter Spreadborough 	}
803*0c036a14SPeter Spreadborough 
804*0c036a14SPeter Spreadborough 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
805*0c036a14SPeter Spreadborough 		ulp_bs_pull_msb(blob->data, data, offset, len);
806*0c036a14SPeter Spreadborough 	else
807*0c036a14SPeter Spreadborough 		ulp_bs_pull_lsb(blob->data, data, data_size, offset, len);
808*0c036a14SPeter Spreadborough 	return 0;
809*0c036a14SPeter Spreadborough }
810afd35335SKishore Padmanabha 
811afd35335SKishore Padmanabha /*
812*0c036a14SPeter Spreadborough  * Get the data portion of the binary blob.
81388badb3aSMike Baucom  *
814*0c036a14SPeter Spreadborough  * blob [in] The blob's data to be retrieved. The blob must be
815*0c036a14SPeter Spreadborough  * initialized prior to pushing data.
81688badb3aSMike Baucom  *
817*0c036a14SPeter Spreadborough  * datalen [out] The number of bits that are filled.
81888badb3aSMike Baucom  *
819*0c036a14SPeter Spreadborough  * Returns a byte array of the blob data or NULL on error.
82088badb3aSMike Baucom  */
821*0c036a14SPeter Spreadborough static inline uint8_t *
822*0c036a14SPeter Spreadborough ulp_blob_data_get(struct ulp_blob *blob,
823*0c036a14SPeter Spreadborough 		  uint16_t *datalen)
824*0c036a14SPeter Spreadborough {
825*0c036a14SPeter Spreadborough 	/* validate the arguments */
826*0c036a14SPeter Spreadborough 	if (unlikely(!blob)) {
827*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
828*0c036a14SPeter Spreadborough 		return NULL; /* failure */
829*0c036a14SPeter Spreadborough 	}
830*0c036a14SPeter Spreadborough 	*datalen = blob->write_idx;
831*0c036a14SPeter Spreadborough 	return blob->data;
832*0c036a14SPeter Spreadborough }
83388badb3aSMike Baucom 
83488badb3aSMike Baucom /*
835*0c036a14SPeter Spreadborough  * Get the data length of the binary blob.
8363fe124d2SKishore Padmanabha  *
837*0c036a14SPeter Spreadborough  * blob [in] The blob's data len to be retrieved.
8383fe124d2SKishore Padmanabha  *
839*0c036a14SPeter Spreadborough  * returns length of the binary blob
8403fe124d2SKishore Padmanabha  */
841*0c036a14SPeter Spreadborough static inline uint16_t
842*0c036a14SPeter Spreadborough ulp_blob_data_len_get(struct ulp_blob *blob)
843*0c036a14SPeter Spreadborough {
844*0c036a14SPeter Spreadborough 	/* validate the arguments */
845*0c036a14SPeter Spreadborough 	if (unlikely(!blob)) {
846*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
847*0c036a14SPeter Spreadborough 		return 0; /* failure */
848*0c036a14SPeter Spreadborough 	}
849*0c036a14SPeter Spreadborough 	return blob->write_idx;
850*0c036a14SPeter Spreadborough }
8513fe124d2SKishore Padmanabha 
8523fe124d2SKishore Padmanabha /*
853*0c036a14SPeter Spreadborough  * Set the encap swap start index of the binary blob.
85488badb3aSMike Baucom  *
85588badb3aSMike Baucom  * blob [in] The blob's data to be retrieved. The blob must be
85688badb3aSMike Baucom  * initialized prior to pushing data.
85788badb3aSMike Baucom  *
85888badb3aSMike Baucom  * returns void.
85988badb3aSMike Baucom  */
860*0c036a14SPeter Spreadborough static inline void
861*0c036a14SPeter Spreadborough ulp_blob_encap_swap_idx_set(struct ulp_blob *blob)
862*0c036a14SPeter Spreadborough {
863*0c036a14SPeter Spreadborough 	/* validate the arguments */
864*0c036a14SPeter Spreadborough 	if (unlikely(!blob)) {
865*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
866*0c036a14SPeter Spreadborough 		return; /* failure */
867*0c036a14SPeter Spreadborough 	}
868*0c036a14SPeter Spreadborough 	blob->encap_swap_idx = blob->write_idx;
869*0c036a14SPeter Spreadborough }
87088badb3aSMike Baucom 
87188badb3aSMike Baucom /*
87288badb3aSMike Baucom  * Perform the encap buffer swap to 64 bit reversal.
87388badb3aSMike Baucom  *
87488badb3aSMike Baucom  * blob [in] The blob's data to be used for swap.
87588badb3aSMike Baucom  *
87688badb3aSMike Baucom  * returns void.
87788badb3aSMike Baucom  */
878*0c036a14SPeter Spreadborough static inline void
879*0c036a14SPeter Spreadborough ulp_blob_perform_encap_swap(struct ulp_blob *blob)
880*0c036a14SPeter Spreadborough {
881*0c036a14SPeter Spreadborough 	uint32_t i, idx = 0, end_idx = 0, roundoff;
882*0c036a14SPeter Spreadborough 	uint8_t temp_val_1, temp_val_2;
883*0c036a14SPeter Spreadborough 
884*0c036a14SPeter Spreadborough 	/* validate the arguments */
885*0c036a14SPeter Spreadborough 	if (unlikely(!blob)) {
886*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
887*0c036a14SPeter Spreadborough 		return; /* failure */
888*0c036a14SPeter Spreadborough 	}
889*0c036a14SPeter Spreadborough 	idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx);
890*0c036a14SPeter Spreadborough 	end_idx = ULP_BITS_2_BYTE(blob->write_idx);
891*0c036a14SPeter Spreadborough 	roundoff = ULP_BYTE_2_BITS(ULP_BITS_2_BYTE(end_idx));
892*0c036a14SPeter Spreadborough 	if (roundoff > end_idx) {
893*0c036a14SPeter Spreadborough 		blob->write_idx += ULP_BYTE_2_BITS(roundoff - end_idx);
894*0c036a14SPeter Spreadborough 		end_idx = roundoff;
895*0c036a14SPeter Spreadborough 	}
896*0c036a14SPeter Spreadborough 	while (idx <= end_idx) {
897*0c036a14SPeter Spreadborough 		for (i = 0; i < 4; i = i + 2) {
898*0c036a14SPeter Spreadborough 			temp_val_1 = blob->data[idx + i];
899*0c036a14SPeter Spreadborough 			temp_val_2 = blob->data[idx + i + 1];
900*0c036a14SPeter Spreadborough 			blob->data[idx + i] = blob->data[idx + 6 - i];
901*0c036a14SPeter Spreadborough 			blob->data[idx + i + 1] = blob->data[idx + 7 - i];
902*0c036a14SPeter Spreadborough 			blob->data[idx + 7 - i] = temp_val_2;
903*0c036a14SPeter Spreadborough 			blob->data[idx + 6 - i] = temp_val_1;
904*0c036a14SPeter Spreadborough 		}
905*0c036a14SPeter Spreadborough 		idx += 8;
906*0c036a14SPeter Spreadborough 	}
907*0c036a14SPeter Spreadborough }
90888badb3aSMike Baucom 
90988badb3aSMike Baucom /*
910a4651725SMike Baucom  * Perform the blob buffer reversal byte wise.
911a4651725SMike Baucom  * This api makes the first byte the last and
912a4651725SMike Baucom  * vice-versa.
913a4651725SMike Baucom  *
914a4651725SMike Baucom  * blob [in] The blob's data to be used for swap.
9153fe124d2SKishore Padmanabha  * chunk_size[in] the swap is done within the chunk in bytes
916a4651725SMike Baucom  *
917a4651725SMike Baucom  * returns void.
918a4651725SMike Baucom  */
919*0c036a14SPeter Spreadborough static inline void
9203fe124d2SKishore Padmanabha ulp_blob_perform_byte_reverse(struct ulp_blob *blob,
921*0c036a14SPeter Spreadborough 			      uint32_t chunk_size)
922*0c036a14SPeter Spreadborough {
923*0c036a14SPeter Spreadborough 	uint32_t idx = 0, jdx = 0, num = 0;
924*0c036a14SPeter Spreadborough 	uint8_t xchar;
925*0c036a14SPeter Spreadborough 	uint8_t *buff;
926*0c036a14SPeter Spreadborough 
927*0c036a14SPeter Spreadborough 	/* validate the arguments */
928*0c036a14SPeter Spreadborough 	if (unlikely(!blob)) {
929*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
930*0c036a14SPeter Spreadborough 		return; /* failure */
931*0c036a14SPeter Spreadborough 	}
932*0c036a14SPeter Spreadborough 
933*0c036a14SPeter Spreadborough 	buff = blob->data;
934*0c036a14SPeter Spreadborough 	num = ULP_BITS_2_BYTE(blob->write_idx) / chunk_size;
935*0c036a14SPeter Spreadborough 	for (idx = 0; idx < num; idx++) {
936*0c036a14SPeter Spreadborough 		for (jdx = 0; jdx < chunk_size / 2; jdx++) {
937*0c036a14SPeter Spreadborough 			xchar = buff[jdx];
938*0c036a14SPeter Spreadborough 			buff[jdx] = buff[(chunk_size - 1) - jdx];
939*0c036a14SPeter Spreadborough 			buff[(chunk_size - 1) - jdx] = xchar;
940*0c036a14SPeter Spreadborough 		}
941*0c036a14SPeter Spreadborough 		buff += chunk_size;
942*0c036a14SPeter Spreadborough 	}
943*0c036a14SPeter Spreadborough }
944a4651725SMike Baucom 
945a4651725SMike Baucom /*
9467e604e7fSKishore Padmanabha  * Perform the blob buffer 64 bit word swap.
9477e604e7fSKishore Padmanabha  * This api makes the first 4 bytes the last in
9487e604e7fSKishore Padmanabha  * a given 64 bit value and vice-versa.
9497e604e7fSKishore Padmanabha  *
9507e604e7fSKishore Padmanabha  * blob [in] The blob's data to be used for swap.
9517e604e7fSKishore Padmanabha  *
9527e604e7fSKishore Padmanabha  * returns void.
9537e604e7fSKishore Padmanabha  */
954*0c036a14SPeter Spreadborough static inline void
955*0c036a14SPeter Spreadborough ulp_blob_perform_64B_word_swap(struct ulp_blob *blob)
956*0c036a14SPeter Spreadborough {
957*0c036a14SPeter Spreadborough 	uint32_t i, j, num;
958*0c036a14SPeter Spreadborough 	uint8_t xchar;
959*0c036a14SPeter Spreadborough 	uint32_t word_size = ULP_64B_IN_BYTES / 2;
960*0c036a14SPeter Spreadborough 
961*0c036a14SPeter Spreadborough 	/* validate the arguments */
962*0c036a14SPeter Spreadborough 	if (unlikely(!blob)) {
963*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
964*0c036a14SPeter Spreadborough 		return; /* failure */
965*0c036a14SPeter Spreadborough 	}
966*0c036a14SPeter Spreadborough 	num = ULP_BITS_2_BYTE(blob->write_idx);
967*0c036a14SPeter Spreadborough 	for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
968*0c036a14SPeter Spreadborough 		for (j = 0; j < word_size; j++) {
969*0c036a14SPeter Spreadborough 			xchar = blob->data[i + j];
970*0c036a14SPeter Spreadborough 			blob->data[i + j] = blob->data[i + j + word_size];
971*0c036a14SPeter Spreadborough 			blob->data[i + j + word_size] = xchar;
972*0c036a14SPeter Spreadborough 		}
973*0c036a14SPeter Spreadborough 	}
974*0c036a14SPeter Spreadborough }
9757e604e7fSKishore Padmanabha 
9767e604e7fSKishore Padmanabha /*
9777e604e7fSKishore Padmanabha  * Perform the blob buffer 64 bit byte swap.
9787e604e7fSKishore Padmanabha  * This api makes the first byte the last in
9797e604e7fSKishore Padmanabha  * a given 64 bit value and vice-versa.
9807e604e7fSKishore Padmanabha  *
9817e604e7fSKishore Padmanabha  * blob [in] The blob's data to be used for swap.
9827e604e7fSKishore Padmanabha  *
9837e604e7fSKishore Padmanabha  * returns void.
9847e604e7fSKishore Padmanabha  */
985*0c036a14SPeter Spreadborough static inline void
986*0c036a14SPeter Spreadborough ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob)
987*0c036a14SPeter Spreadborough {
988*0c036a14SPeter Spreadborough 	uint32_t i, j, num;
989*0c036a14SPeter Spreadborough 	uint8_t xchar;
990*0c036a14SPeter Spreadborough 	uint32_t offset = ULP_64B_IN_BYTES - 1;
991*0c036a14SPeter Spreadborough 
992*0c036a14SPeter Spreadborough 	/* validate the arguments */
993*0c036a14SPeter Spreadborough 	if (unlikely(!blob)) {
994*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
995*0c036a14SPeter Spreadborough 		return; /* failure */
996*0c036a14SPeter Spreadborough 	}
997*0c036a14SPeter Spreadborough 	num = ULP_BITS_2_BYTE(blob->write_idx);
998*0c036a14SPeter Spreadborough 	for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
999*0c036a14SPeter Spreadborough 		for (j = 0; j < (ULP_64B_IN_BYTES / 2); j++) {
1000*0c036a14SPeter Spreadborough 			xchar = blob->data[i + j];
1001*0c036a14SPeter Spreadborough 			blob->data[i + j] = blob->data[i + offset - j];
1002*0c036a14SPeter Spreadborough 			blob->data[i + offset - j] = xchar;
1003*0c036a14SPeter Spreadborough 		}
1004*0c036a14SPeter Spreadborough 	}
1005*0c036a14SPeter Spreadborough }
10067e604e7fSKishore Padmanabha 
10077e604e7fSKishore Padmanabha /*
10083fe124d2SKishore Padmanabha  * Perform the blob buffer merge.
10093fe124d2SKishore Padmanabha  * This api makes the src blob merged to the dst blob.
10103fe124d2SKishore Padmanabha  * The block size and pad size help in padding the dst blob
10113fe124d2SKishore Padmanabha  *
10123fe124d2SKishore Padmanabha  * dst [in] The destination blob, the blob to be merged.
10133fe124d2SKishore Padmanabha  * src [in] The src blob.
1014*0c036a14SPeter Spreadborough  * block_size [in] The size of the block in bytes after which padding gets
1015*0c036a14SPeter Spreadborough  *                 applied.
10163fe124d2SKishore Padmanabha  * pad [in] The size of the pad to be applied.
10173fe124d2SKishore Padmanabha  *
10183fe124d2SKishore Padmanabha  * returns 0 on success.
10193fe124d2SKishore Padmanabha  */
1020*0c036a14SPeter Spreadborough static inline int32_t
1021*0c036a14SPeter Spreadborough ulp_blob_msb_block_merge(struct ulp_blob *dst, struct ulp_blob *src,
1022*0c036a14SPeter Spreadborough 			 uint32_t block_size, uint32_t pad)
1023*0c036a14SPeter Spreadborough {
1024*0c036a14SPeter Spreadborough 	uint32_t i, k, write_bytes, remaining;
1025*0c036a14SPeter Spreadborough 	uint16_t num;
1026*0c036a14SPeter Spreadborough 	uint8_t *src_buf = ulp_blob_data_get(src, &num);
1027*0c036a14SPeter Spreadborough 	uint8_t bluff;
1028*0c036a14SPeter Spreadborough 
1029*0c036a14SPeter Spreadborough 	for (i = 0; i < num;) {
1030*0c036a14SPeter Spreadborough 		if (((dst->write_idx % block_size) + (num - i)) > block_size)
1031*0c036a14SPeter Spreadborough 			write_bytes = block_size -
1032*0c036a14SPeter Spreadborough 				(dst->write_idx % block_size);
1033*0c036a14SPeter Spreadborough 		else
1034*0c036a14SPeter Spreadborough 			write_bytes = num - i;
1035*0c036a14SPeter Spreadborough 		for (k = 0; k < ULP_BITS_2_BYTE_NR(write_bytes); k++) {
1036*0c036a14SPeter Spreadborough 			ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE,
1037*0c036a14SPeter Spreadborough 				       *src_buf);
1038*0c036a14SPeter Spreadborough 			dst->write_idx += ULP_BLOB_BYTE;
1039*0c036a14SPeter Spreadborough 			src_buf++;
1040*0c036a14SPeter Spreadborough 		}
1041*0c036a14SPeter Spreadborough 		remaining = write_bytes % ULP_BLOB_BYTE;
1042*0c036a14SPeter Spreadborough 		if (remaining) {
1043*0c036a14SPeter Spreadborough 			bluff = (*src_buf) & ((uint8_t)-1 <<
1044*0c036a14SPeter Spreadborough 					      (ULP_BLOB_BYTE - remaining));
1045*0c036a14SPeter Spreadborough 			ulp_bs_put_msb(dst->data, dst->write_idx,
1046*0c036a14SPeter Spreadborough 				       ULP_BLOB_BYTE, bluff);
1047*0c036a14SPeter Spreadborough 			dst->write_idx += remaining;
1048*0c036a14SPeter Spreadborough 		}
1049*0c036a14SPeter Spreadborough 		if (write_bytes != (num - i)) {
1050*0c036a14SPeter Spreadborough 			/* add the padding */
1051*0c036a14SPeter Spreadborough 			ulp_blob_pad_push(dst, pad);
1052*0c036a14SPeter Spreadborough 			if (remaining) {
1053*0c036a14SPeter Spreadborough 				ulp_bs_put_msb(dst->data, dst->write_idx,
1054*0c036a14SPeter Spreadborough 					       ULP_BLOB_BYTE - remaining,
1055*0c036a14SPeter Spreadborough 					       *src_buf);
1056*0c036a14SPeter Spreadborough 				dst->write_idx += ULP_BLOB_BYTE - remaining;
1057*0c036a14SPeter Spreadborough 				src_buf++;
1058*0c036a14SPeter Spreadborough 			}
1059*0c036a14SPeter Spreadborough 		}
1060*0c036a14SPeter Spreadborough 		i += write_bytes;
1061*0c036a14SPeter Spreadborough 	}
1062*0c036a14SPeter Spreadborough 	return 0;
1063*0c036a14SPeter Spreadborough }
10643fe124d2SKishore Padmanabha 
10653fe124d2SKishore Padmanabha /*
1066*0c036a14SPeter Spreadborough  * Perform the blob buffer merge.
1067*0c036a14SPeter Spreadborough  * This api makes the src blob merged to the dst blob.
1068*0c036a14SPeter Spreadborough  * The block size and pad size help in padding the dst blob
10693fe124d2SKishore Padmanabha  *
1070*0c036a14SPeter Spreadborough  * dst [in] The destination blob, the blob to be merged.
1071*0c036a14SPeter Spreadborough  * src [in] The src blob.
1072*0c036a14SPeter Spreadborough  * block_size [in] The size of the block in bytes after which padding gets
1073*0c036a14SPeter Spreadborough  *                 applied.
1074*0c036a14SPeter Spreadborough  * pad [in] The size of the pad to be applied.
10753fe124d2SKishore Padmanabha  *
1076*0c036a14SPeter Spreadborough  * returns 0 on success.
10773fe124d2SKishore Padmanabha  */
1078*0c036a14SPeter Spreadborough static inline int32_t
1079*0c036a14SPeter Spreadborough ulp_blob_block_merge(struct ulp_blob *dst, struct ulp_blob *src,
1080*0c036a14SPeter Spreadborough 		     uint32_t block_size, uint32_t pad)
1081*0c036a14SPeter Spreadborough {
1082*0c036a14SPeter Spreadborough 	if (dst->byte_order == BNXT_ULP_BYTE_ORDER_BE &&
1083*0c036a14SPeter Spreadborough 	    src->byte_order == BNXT_ULP_BYTE_ORDER_BE)
1084*0c036a14SPeter Spreadborough 		return ulp_blob_msb_block_merge(dst, src, block_size, pad);
1085*0c036a14SPeter Spreadborough 
1086*0c036a14SPeter Spreadborough 	BNXT_DRV_DBG(ERR, "block merge not implemented yet\n");
1087*0c036a14SPeter Spreadborough 	return -EINVAL;
1088*0c036a14SPeter Spreadborough }
1089*0c036a14SPeter Spreadborough 
1090*0c036a14SPeter Spreadborough /*
1091*0c036a14SPeter Spreadborough  * Perform the blob buffer append.
1092*0c036a14SPeter Spreadborough  *
1093*0c036a14SPeter Spreadborough  * dst [in] The destination blob, the blob to be merged.
1094*0c036a14SPeter Spreadborough  * src [in] The src blob.
1095*0c036a14SPeter Spreadborough  * src_offset [in] Offset of src data.
1096*0c036a14SPeter Spreadborough  * src_len [in] The size of the src data.
1097*0c036a14SPeter Spreadborough  *
1098*0c036a14SPeter Spreadborough  * returns 0 on success.
1099*0c036a14SPeter Spreadborough  */
1100*0c036a14SPeter Spreadborough static inline int32_t
11013fe124d2SKishore Padmanabha ulp_blob_append(struct ulp_blob *dst, struct ulp_blob *src,
1102*0c036a14SPeter Spreadborough 		uint16_t src_offset, uint16_t src_len)
1103*0c036a14SPeter Spreadborough {
1104*0c036a14SPeter Spreadborough 	uint32_t k, remaining = 0;
1105*0c036a14SPeter Spreadborough 	uint16_t num;
1106*0c036a14SPeter Spreadborough 	uint8_t bluff;
1107*0c036a14SPeter Spreadborough 	uint8_t *src_buf = ulp_blob_data_get(src, &num);
1108*0c036a14SPeter Spreadborough 
1109*0c036a14SPeter Spreadborough 	if (unlikely((src_offset + src_len) > num))
1110*0c036a14SPeter Spreadborough 		return -EINVAL;
1111*0c036a14SPeter Spreadborough 
1112*0c036a14SPeter Spreadborough 	/* Only supporting BE for now */
1113*0c036a14SPeter Spreadborough 	if (unlikely(src->byte_order != BNXT_ULP_BYTE_ORDER_BE ||
1114*0c036a14SPeter Spreadborough 		     dst->byte_order != BNXT_ULP_BYTE_ORDER_BE))
1115*0c036a14SPeter Spreadborough 		return -EINVAL;
1116*0c036a14SPeter Spreadborough 
1117*0c036a14SPeter Spreadborough 	/* Handle if the source offset is not on a byte boundary */
1118*0c036a14SPeter Spreadborough 	remaining = src_offset % ULP_BLOB_BYTE;
1119*0c036a14SPeter Spreadborough 	if (remaining) {
1120*0c036a14SPeter Spreadborough 		bluff = src_buf[src_offset / ULP_BLOB_BYTE] & ((uint8_t)-1 >>
1121*0c036a14SPeter Spreadborough 				      (ULP_BLOB_BYTE - remaining));
1122*0c036a14SPeter Spreadborough 		ulp_bs_put_msb(dst->data, dst->write_idx, remaining, bluff);
1123*0c036a14SPeter Spreadborough 		dst->write_idx += remaining;
1124*0c036a14SPeter Spreadborough 		src_offset += remaining;
1125*0c036a14SPeter Spreadborough 	}
1126*0c036a14SPeter Spreadborough 
1127*0c036a14SPeter Spreadborough 	src_buf += ULP_BITS_2_BYTE_NR(src_offset);
1128*0c036a14SPeter Spreadborough 
1129*0c036a14SPeter Spreadborough 	/* Push the byte aligned pieces */
1130*0c036a14SPeter Spreadborough 	for (k = 0; k < ULP_BITS_2_BYTE_NR(src_len); k++) {
1131*0c036a14SPeter Spreadborough 		ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE,
1132*0c036a14SPeter Spreadborough 			       *src_buf);
1133*0c036a14SPeter Spreadborough 		dst->write_idx += ULP_BLOB_BYTE;
1134*0c036a14SPeter Spreadborough 		src_buf++;
1135*0c036a14SPeter Spreadborough 	}
1136*0c036a14SPeter Spreadborough 
1137*0c036a14SPeter Spreadborough 	/* Handle the remaining if length is not a byte boundary */
1138*0c036a14SPeter Spreadborough 	if (src_len > remaining)
1139*0c036a14SPeter Spreadborough 		remaining = (src_len - remaining) % ULP_BLOB_BYTE;
1140*0c036a14SPeter Spreadborough 	else
1141*0c036a14SPeter Spreadborough 		remaining = 0;
1142*0c036a14SPeter Spreadborough 	if (remaining) {
1143*0c036a14SPeter Spreadborough 		bluff = (*src_buf) & ((uint8_t)-1 <<
1144*0c036a14SPeter Spreadborough 				      (ULP_BLOB_BYTE - remaining));
1145*0c036a14SPeter Spreadborough 		ulp_bs_put_msb(dst->data, dst->write_idx,
1146*0c036a14SPeter Spreadborough 			       ULP_BLOB_BYTE, bluff);
1147*0c036a14SPeter Spreadborough 		dst->write_idx += remaining;
1148*0c036a14SPeter Spreadborough 	}
1149*0c036a14SPeter Spreadborough 
1150*0c036a14SPeter Spreadborough 	return 0;
1151*0c036a14SPeter Spreadborough }
11523fe124d2SKishore Padmanabha 
11533fe124d2SKishore Padmanabha /*
1154f63aa27dSKishore Padmanabha  * Perform the blob buffer copy.
1155f63aa27dSKishore Padmanabha  * This api makes the src blob merged to the dst blob.
1156f63aa27dSKishore Padmanabha  *
1157f63aa27dSKishore Padmanabha  * dst [in] The destination blob, the blob to be merged.
1158f63aa27dSKishore Padmanabha  * src [in] The src blob.
1159f63aa27dSKishore Padmanabha  *
1160f63aa27dSKishore Padmanabha  * returns 0 on success.
1161f63aa27dSKishore Padmanabha  */
1162*0c036a14SPeter Spreadborough static inline int32_t
1163*0c036a14SPeter Spreadborough ulp_blob_buffer_copy(struct ulp_blob *dst, struct ulp_blob *src)
1164*0c036a14SPeter Spreadborough {
1165*0c036a14SPeter Spreadborough 	if (unlikely((dst->write_idx + src->write_idx) > dst->bitlen)) {
1166*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "source buffer too large\n");
1167*0c036a14SPeter Spreadborough 		return -EINVAL;
1168*0c036a14SPeter Spreadborough 	}
1169*0c036a14SPeter Spreadborough 	if (unlikely(ULP_BITS_IS_BYTE_NOT_ALIGNED(dst->write_idx) ||
1170*0c036a14SPeter Spreadborough 		     ULP_BITS_IS_BYTE_NOT_ALIGNED(src->write_idx))) {
1171*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "source buffer is not aligned\n");
1172*0c036a14SPeter Spreadborough 		return -EINVAL;
1173*0c036a14SPeter Spreadborough 	}
1174*0c036a14SPeter Spreadborough 	memcpy(&dst->data[ULP_BITS_2_BYTE_NR(dst->write_idx)],
1175*0c036a14SPeter Spreadborough 	       src->data, ULP_BITS_2_BYTE_NR(src->write_idx));
1176*0c036a14SPeter Spreadborough 	dst->write_idx += src->write_idx;
1177*0c036a14SPeter Spreadborough 	return 0;
1178*0c036a14SPeter Spreadborough }
1179f63aa27dSKishore Padmanabha 
1180f63aa27dSKishore Padmanabha /*
118188badb3aSMike Baucom  * Read data from the operand
118288badb3aSMike Baucom  *
118388badb3aSMike Baucom  * operand [in] A pointer to a 16 Byte operand
118488badb3aSMike Baucom  *
118588badb3aSMike Baucom  * val [in/out] The variable to copy the operand to
118688badb3aSMike Baucom  *
1187*0c036a14SPeter Spreadborough  * bytes [in] The number of bytes to read into val
118888badb3aSMike Baucom  *
1189c569279aSShuanglin Wang  * returns zero on success.
119088badb3aSMike Baucom  */
1191*0c036a14SPeter Spreadborough static inline int32_t
119288badb3aSMike Baucom ulp_operand_read(uint8_t *operand,
119388badb3aSMike Baucom 		 uint8_t *val,
1194*0c036a14SPeter Spreadborough 		 uint16_t bytes)
1195*0c036a14SPeter Spreadborough {
1196*0c036a14SPeter Spreadborough 	/* validate the arguments */
1197*0c036a14SPeter Spreadborough 	if (unlikely(!operand || !val)) {
1198*0c036a14SPeter Spreadborough 		BNXT_DRV_DBG(ERR, "invalid argument\n");
1199*0c036a14SPeter Spreadborough 		return -EINVAL;
1200*0c036a14SPeter Spreadborough 	}
1201*0c036a14SPeter Spreadborough 	memcpy(val, operand, bytes);
1202*0c036a14SPeter Spreadborough 	return 0;
1203*0c036a14SPeter Spreadborough }
12042bbcdee8SKishore Padmanabha 
12052bbcdee8SKishore Padmanabha /* Function to check if bitmap is ones. Return 1 on success */
1206*0c036a14SPeter Spreadborough static inline uint32_t
1207*0c036a14SPeter Spreadborough ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size)
1208*0c036a14SPeter Spreadborough {
1209*0c036a14SPeter Spreadborough 	while (size-- > 0) {
1210*0c036a14SPeter Spreadborough 		if (*bitmap != 0xFF)
1211*0c036a14SPeter Spreadborough 			return 0;
1212*0c036a14SPeter Spreadborough 		bitmap++;
1213*0c036a14SPeter Spreadborough 	}
1214*0c036a14SPeter Spreadborough 	return 1;
1215*0c036a14SPeter Spreadborough }
12162bbcdee8SKishore Padmanabha 
12172bbcdee8SKishore Padmanabha /* Function to check if bitmap is not zero. Return 1 on success */
1218*0c036a14SPeter Spreadborough static inline uint32_t
1219*0c036a14SPeter Spreadborough ulp_bitmap_notzero(const uint8_t *bitmap, int32_t size)
1220*0c036a14SPeter Spreadborough {
1221*0c036a14SPeter Spreadborough 	while (size-- > 0) {
1222*0c036a14SPeter Spreadborough 		if (*bitmap != 0)
1223*0c036a14SPeter Spreadborough 			return 1;
1224*0c036a14SPeter Spreadborough 		bitmap++;
1225*0c036a14SPeter Spreadborough 	}
1226*0c036a14SPeter Spreadborough 	return 0;
1227*0c036a14SPeter Spreadborough }
12282bbcdee8SKishore Padmanabha 
12290001cc58SKishore Padmanabha /* returns 0 if input is power of 2 */
1230*0c036a14SPeter Spreadborough static inline int32_t
1231*0c036a14SPeter Spreadborough ulp_util_is_power_of_2(uint64_t x)
1232*0c036a14SPeter Spreadborough {
1233*0c036a14SPeter Spreadborough 	if (((x - 1) & x))
1234*0c036a14SPeter Spreadborough 		return -1;
1235*0c036a14SPeter Spreadborough 	return 0;
1236*0c036a14SPeter Spreadborough }
123788badb3aSMike Baucom #endif /* _ULP_UTILS_H_ */
1238