xref: /f-stack/dpdk/drivers/net/bnxt/tf_ulp/ulp_utils.c (revision 2d9fd380)
1*2d9fd380Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*2d9fd380Sjfb8856606  * Copyright(c) 2014-2019 Broadcom
3*2d9fd380Sjfb8856606  * All rights reserved.
4*2d9fd380Sjfb8856606  */
5*2d9fd380Sjfb8856606 
6*2d9fd380Sjfb8856606 #include "ulp_utils.h"
7*2d9fd380Sjfb8856606 #include "bnxt_tf_common.h"
8*2d9fd380Sjfb8856606 
9*2d9fd380Sjfb8856606 /*
10*2d9fd380Sjfb8856606  * Initialize the regfile structure for writing
11*2d9fd380Sjfb8856606  *
12*2d9fd380Sjfb8856606  * regfile [in] Ptr to a regfile instance
13*2d9fd380Sjfb8856606  *
14*2d9fd380Sjfb8856606  * returns 0 on error or 1 on success
15*2d9fd380Sjfb8856606  */
16*2d9fd380Sjfb8856606 uint32_t
ulp_regfile_init(struct ulp_regfile * regfile)17*2d9fd380Sjfb8856606 ulp_regfile_init(struct ulp_regfile *regfile)
18*2d9fd380Sjfb8856606 {
19*2d9fd380Sjfb8856606 	/* validate the arguments */
20*2d9fd380Sjfb8856606 	if (!regfile) {
21*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
22*2d9fd380Sjfb8856606 		return 0; /* failure */
23*2d9fd380Sjfb8856606 	}
24*2d9fd380Sjfb8856606 	memset(regfile, 0, sizeof(struct ulp_regfile));
25*2d9fd380Sjfb8856606 	return 1; /* Success */
26*2d9fd380Sjfb8856606 }
27*2d9fd380Sjfb8856606 
28*2d9fd380Sjfb8856606 /*
29*2d9fd380Sjfb8856606  * Read a value from the regfile
30*2d9fd380Sjfb8856606  *
31*2d9fd380Sjfb8856606  * regfile [in] The regfile instance. Must be initialized prior to being used
32*2d9fd380Sjfb8856606  *
33*2d9fd380Sjfb8856606  * field [in] The field to be read within the regfile.
34*2d9fd380Sjfb8856606  *
35*2d9fd380Sjfb8856606  * data [in/out]
36*2d9fd380Sjfb8856606  *
37*2d9fd380Sjfb8856606  * returns size, zero on failure
38*2d9fd380Sjfb8856606  */
39*2d9fd380Sjfb8856606 uint32_t
ulp_regfile_read(struct ulp_regfile * regfile,enum bnxt_ulp_regfile_index field,uint64_t * data)40*2d9fd380Sjfb8856606 ulp_regfile_read(struct ulp_regfile *regfile,
41*2d9fd380Sjfb8856606 		 enum bnxt_ulp_regfile_index field,
42*2d9fd380Sjfb8856606 		 uint64_t *data)
43*2d9fd380Sjfb8856606 {
44*2d9fd380Sjfb8856606 	/* validate the arguments */
45*2d9fd380Sjfb8856606 	if (!regfile || field >= BNXT_ULP_REGFILE_INDEX_LAST) {
46*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
47*2d9fd380Sjfb8856606 		return 0; /* failure */
48*2d9fd380Sjfb8856606 	}
49*2d9fd380Sjfb8856606 
50*2d9fd380Sjfb8856606 	*data = regfile->entry[field].data;
51*2d9fd380Sjfb8856606 	return sizeof(*data);
52*2d9fd380Sjfb8856606 }
53*2d9fd380Sjfb8856606 
54*2d9fd380Sjfb8856606 /*
55*2d9fd380Sjfb8856606  * Write a value to the regfile
56*2d9fd380Sjfb8856606  *
57*2d9fd380Sjfb8856606  * regfile [in] The regfile instance.  Must be initialized prior to being used
58*2d9fd380Sjfb8856606  *
59*2d9fd380Sjfb8856606  * field [in] The field to be written within the regfile.
60*2d9fd380Sjfb8856606  *
61*2d9fd380Sjfb8856606  * data [in] The value is written into this variable.  It is going to be in the
62*2d9fd380Sjfb8856606  * same byte order as it was written.
63*2d9fd380Sjfb8856606  *
64*2d9fd380Sjfb8856606  * size [in] The size in bytes of the value beingritten into this
65*2d9fd380Sjfb8856606  * variable.
66*2d9fd380Sjfb8856606  *
67*2d9fd380Sjfb8856606  * returns 0 on fail
68*2d9fd380Sjfb8856606  */
69*2d9fd380Sjfb8856606 uint32_t
ulp_regfile_write(struct ulp_regfile * regfile,enum bnxt_ulp_regfile_index field,uint64_t data)70*2d9fd380Sjfb8856606 ulp_regfile_write(struct ulp_regfile *regfile,
71*2d9fd380Sjfb8856606 		  enum bnxt_ulp_regfile_index field,
72*2d9fd380Sjfb8856606 		  uint64_t data)
73*2d9fd380Sjfb8856606 {
74*2d9fd380Sjfb8856606 	/* validate the arguments */
75*2d9fd380Sjfb8856606 	if (!regfile || field >= BNXT_ULP_REGFILE_INDEX_LAST) {
76*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
77*2d9fd380Sjfb8856606 		return 0; /* failure */
78*2d9fd380Sjfb8856606 	}
79*2d9fd380Sjfb8856606 
80*2d9fd380Sjfb8856606 	regfile->entry[field].data = data;
81*2d9fd380Sjfb8856606 	return sizeof(data); /* Success */
82*2d9fd380Sjfb8856606 }
83*2d9fd380Sjfb8856606 
84*2d9fd380Sjfb8856606 static void
ulp_bs_put_msb(uint8_t * bs,uint16_t bitpos,uint8_t bitlen,uint8_t val)85*2d9fd380Sjfb8856606 ulp_bs_put_msb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
86*2d9fd380Sjfb8856606 {
87*2d9fd380Sjfb8856606 	uint8_t bitoffs = bitpos % 8;
88*2d9fd380Sjfb8856606 	uint16_t index  = bitpos / 8;
89*2d9fd380Sjfb8856606 	uint8_t mask;
90*2d9fd380Sjfb8856606 	uint8_t tmp;
91*2d9fd380Sjfb8856606 	int8_t shift;
92*2d9fd380Sjfb8856606 
93*2d9fd380Sjfb8856606 	tmp = bs[index];
94*2d9fd380Sjfb8856606 	mask = ((uint8_t)-1 >> (8 - bitlen));
95*2d9fd380Sjfb8856606 	shift = 8 - bitoffs - bitlen;
96*2d9fd380Sjfb8856606 	val &= mask;
97*2d9fd380Sjfb8856606 
98*2d9fd380Sjfb8856606 	if (shift >= 0) {
99*2d9fd380Sjfb8856606 		tmp &= ~(mask << shift);
100*2d9fd380Sjfb8856606 		tmp |= val << shift;
101*2d9fd380Sjfb8856606 		bs[index] = tmp;
102*2d9fd380Sjfb8856606 	} else {
103*2d9fd380Sjfb8856606 		tmp &= ~((uint8_t)-1 >> bitoffs);
104*2d9fd380Sjfb8856606 		tmp |= val >> -shift;
105*2d9fd380Sjfb8856606 		bs[index++] = tmp;
106*2d9fd380Sjfb8856606 
107*2d9fd380Sjfb8856606 		tmp = bs[index];
108*2d9fd380Sjfb8856606 		tmp &= ((uint8_t)-1 >> (bitlen - (8 - bitoffs)));
109*2d9fd380Sjfb8856606 		tmp |= val << (8 + shift);
110*2d9fd380Sjfb8856606 		bs[index] = tmp;
111*2d9fd380Sjfb8856606 	}
112*2d9fd380Sjfb8856606 }
113*2d9fd380Sjfb8856606 
114*2d9fd380Sjfb8856606 static void
ulp_bs_put_lsb(uint8_t * bs,uint16_t bitpos,uint8_t bitlen,uint8_t val)115*2d9fd380Sjfb8856606 ulp_bs_put_lsb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
116*2d9fd380Sjfb8856606 {
117*2d9fd380Sjfb8856606 	uint8_t bitoffs = bitpos % 8;
118*2d9fd380Sjfb8856606 	uint16_t index  = bitpos / 8;
119*2d9fd380Sjfb8856606 	uint8_t mask;
120*2d9fd380Sjfb8856606 	uint8_t tmp;
121*2d9fd380Sjfb8856606 	uint8_t shift;
122*2d9fd380Sjfb8856606 	uint8_t partial;
123*2d9fd380Sjfb8856606 
124*2d9fd380Sjfb8856606 	tmp = bs[index];
125*2d9fd380Sjfb8856606 	shift = bitoffs;
126*2d9fd380Sjfb8856606 
127*2d9fd380Sjfb8856606 	if (bitoffs + bitlen <= 8) {
128*2d9fd380Sjfb8856606 		mask = ((1 << bitlen) - 1) << shift;
129*2d9fd380Sjfb8856606 		tmp &= ~mask;
130*2d9fd380Sjfb8856606 		tmp |= ((val << shift) & mask);
131*2d9fd380Sjfb8856606 		bs[index] = tmp;
132*2d9fd380Sjfb8856606 	} else {
133*2d9fd380Sjfb8856606 		partial = 8 - bitoffs;
134*2d9fd380Sjfb8856606 		mask = ((1 << partial) - 1) << shift;
135*2d9fd380Sjfb8856606 		tmp &= ~mask;
136*2d9fd380Sjfb8856606 		tmp |= ((val << shift) & mask);
137*2d9fd380Sjfb8856606 		bs[index++] = tmp;
138*2d9fd380Sjfb8856606 
139*2d9fd380Sjfb8856606 		val >>= partial;
140*2d9fd380Sjfb8856606 		partial = bitlen - partial;
141*2d9fd380Sjfb8856606 		mask = ((1 << partial) - 1);
142*2d9fd380Sjfb8856606 		tmp = bs[index];
143*2d9fd380Sjfb8856606 		tmp &= ~mask;
144*2d9fd380Sjfb8856606 		tmp |= (val & mask);
145*2d9fd380Sjfb8856606 		bs[index] = tmp;
146*2d9fd380Sjfb8856606 	}
147*2d9fd380Sjfb8856606 }
148*2d9fd380Sjfb8856606 
149*2d9fd380Sjfb8856606 /* Assuming that val is in Big-Endian Format */
150*2d9fd380Sjfb8856606 static uint32_t
ulp_bs_push_lsb(uint8_t * bs,uint16_t pos,uint8_t len,uint8_t * val)151*2d9fd380Sjfb8856606 ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
152*2d9fd380Sjfb8856606 {
153*2d9fd380Sjfb8856606 	int i;
154*2d9fd380Sjfb8856606 	int cnt = (len) / 8;
155*2d9fd380Sjfb8856606 	int tlen = len;
156*2d9fd380Sjfb8856606 
157*2d9fd380Sjfb8856606 	if (cnt > 0 && !(len % 8))
158*2d9fd380Sjfb8856606 		cnt -= 1;
159*2d9fd380Sjfb8856606 
160*2d9fd380Sjfb8856606 	for (i = 0; i < cnt; i++) {
161*2d9fd380Sjfb8856606 		ulp_bs_put_lsb(bs, pos, 8, val[cnt - i]);
162*2d9fd380Sjfb8856606 		pos += 8;
163*2d9fd380Sjfb8856606 		tlen -= 8;
164*2d9fd380Sjfb8856606 	}
165*2d9fd380Sjfb8856606 
166*2d9fd380Sjfb8856606 	/* Handle the remainder bits */
167*2d9fd380Sjfb8856606 	if (tlen)
168*2d9fd380Sjfb8856606 		ulp_bs_put_lsb(bs, pos, tlen, val[0]);
169*2d9fd380Sjfb8856606 	return len;
170*2d9fd380Sjfb8856606 }
171*2d9fd380Sjfb8856606 
172*2d9fd380Sjfb8856606 /* Assuming that val is in Big-Endian Format */
173*2d9fd380Sjfb8856606 static uint32_t
ulp_bs_push_msb(uint8_t * bs,uint16_t pos,uint8_t len,uint8_t * val)174*2d9fd380Sjfb8856606 ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
175*2d9fd380Sjfb8856606 {
176*2d9fd380Sjfb8856606 	int i;
177*2d9fd380Sjfb8856606 	int cnt = (len + 7) / 8;
178*2d9fd380Sjfb8856606 	int tlen = len;
179*2d9fd380Sjfb8856606 
180*2d9fd380Sjfb8856606 	/* Handle any remainder bits */
181*2d9fd380Sjfb8856606 	int tmp = len % 8;
182*2d9fd380Sjfb8856606 
183*2d9fd380Sjfb8856606 	if (!tmp)
184*2d9fd380Sjfb8856606 		tmp = 8;
185*2d9fd380Sjfb8856606 
186*2d9fd380Sjfb8856606 	ulp_bs_put_msb(bs, pos, tmp, val[0]);
187*2d9fd380Sjfb8856606 
188*2d9fd380Sjfb8856606 	pos += tmp;
189*2d9fd380Sjfb8856606 	tlen -= tmp;
190*2d9fd380Sjfb8856606 
191*2d9fd380Sjfb8856606 	for (i = 1; i < cnt; i++) {
192*2d9fd380Sjfb8856606 		ulp_bs_put_msb(bs, pos, 8, val[i]);
193*2d9fd380Sjfb8856606 		pos += 8;
194*2d9fd380Sjfb8856606 		tlen -= 8;
195*2d9fd380Sjfb8856606 	}
196*2d9fd380Sjfb8856606 
197*2d9fd380Sjfb8856606 	return len;
198*2d9fd380Sjfb8856606 }
199*2d9fd380Sjfb8856606 
200*2d9fd380Sjfb8856606 /*
201*2d9fd380Sjfb8856606  * Initializes the blob structure for creating binary blob
202*2d9fd380Sjfb8856606  *
203*2d9fd380Sjfb8856606  * blob [in] The blob to be initialized
204*2d9fd380Sjfb8856606  *
205*2d9fd380Sjfb8856606  * bitlen [in] The bit length of the blob
206*2d9fd380Sjfb8856606  *
207*2d9fd380Sjfb8856606  * order [in] The byte order for the blob.  Currently only supporting
208*2d9fd380Sjfb8856606  * big endian.  All fields are packed with this order.
209*2d9fd380Sjfb8856606  *
210*2d9fd380Sjfb8856606  * returns 0 on error or 1 on success
211*2d9fd380Sjfb8856606  */
212*2d9fd380Sjfb8856606 uint32_t
ulp_blob_init(struct ulp_blob * blob,uint16_t bitlen,enum bnxt_ulp_byte_order order)213*2d9fd380Sjfb8856606 ulp_blob_init(struct ulp_blob *blob,
214*2d9fd380Sjfb8856606 	      uint16_t bitlen,
215*2d9fd380Sjfb8856606 	      enum bnxt_ulp_byte_order order)
216*2d9fd380Sjfb8856606 {
217*2d9fd380Sjfb8856606 	/* validate the arguments */
218*2d9fd380Sjfb8856606 	if (!blob || bitlen > (8 * sizeof(blob->data))) {
219*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
220*2d9fd380Sjfb8856606 		return 0; /* failure */
221*2d9fd380Sjfb8856606 	}
222*2d9fd380Sjfb8856606 	blob->bitlen = bitlen;
223*2d9fd380Sjfb8856606 	blob->byte_order = order;
224*2d9fd380Sjfb8856606 	blob->write_idx = 0;
225*2d9fd380Sjfb8856606 	memset(blob->data, 0, sizeof(blob->data));
226*2d9fd380Sjfb8856606 	return 1; /* Success */
227*2d9fd380Sjfb8856606 }
228*2d9fd380Sjfb8856606 
229*2d9fd380Sjfb8856606 /*
230*2d9fd380Sjfb8856606  * Add data to the binary blob at the current offset.
231*2d9fd380Sjfb8856606  *
232*2d9fd380Sjfb8856606  * blob [in] The blob that data is added to.  The blob must
233*2d9fd380Sjfb8856606  * be initialized prior to pushing data.
234*2d9fd380Sjfb8856606  *
235*2d9fd380Sjfb8856606  * data [in] A pointer to bytes to be added to the blob.
236*2d9fd380Sjfb8856606  *
237*2d9fd380Sjfb8856606  * datalen [in] The number of bits to be added to the blob.
238*2d9fd380Sjfb8856606  *
239*2d9fd380Sjfb8856606  * The offset of the data is updated after each push of data.
240*2d9fd380Sjfb8856606  * NULL returned on error.
241*2d9fd380Sjfb8856606  */
242*2d9fd380Sjfb8856606 #define ULP_BLOB_BYTE		8
243*2d9fd380Sjfb8856606 #define ULP_BLOB_BYTE_HEX	0xFF
244*2d9fd380Sjfb8856606 #define BLOB_MASK_CAL(x)	((0xFF << (x)) & 0xFF)
245*2d9fd380Sjfb8856606 uint32_t
ulp_blob_push(struct ulp_blob * blob,uint8_t * data,uint32_t datalen)246*2d9fd380Sjfb8856606 ulp_blob_push(struct ulp_blob *blob,
247*2d9fd380Sjfb8856606 	      uint8_t *data,
248*2d9fd380Sjfb8856606 	      uint32_t datalen)
249*2d9fd380Sjfb8856606 {
250*2d9fd380Sjfb8856606 	uint32_t rc;
251*2d9fd380Sjfb8856606 
252*2d9fd380Sjfb8856606 	/* validate the arguments */
253*2d9fd380Sjfb8856606 	if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
254*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
255*2d9fd380Sjfb8856606 		return 0; /* failure */
256*2d9fd380Sjfb8856606 	}
257*2d9fd380Sjfb8856606 
258*2d9fd380Sjfb8856606 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
259*2d9fd380Sjfb8856606 		rc = ulp_bs_push_msb(blob->data,
260*2d9fd380Sjfb8856606 				     blob->write_idx,
261*2d9fd380Sjfb8856606 				     datalen,
262*2d9fd380Sjfb8856606 				     data);
263*2d9fd380Sjfb8856606 	else
264*2d9fd380Sjfb8856606 		rc = ulp_bs_push_lsb(blob->data,
265*2d9fd380Sjfb8856606 				     blob->write_idx,
266*2d9fd380Sjfb8856606 				     datalen,
267*2d9fd380Sjfb8856606 				     data);
268*2d9fd380Sjfb8856606 	if (!rc) {
269*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "Failed ro write blob\n");
270*2d9fd380Sjfb8856606 		return 0;
271*2d9fd380Sjfb8856606 	}
272*2d9fd380Sjfb8856606 	blob->write_idx += datalen;
273*2d9fd380Sjfb8856606 	return datalen;
274*2d9fd380Sjfb8856606 }
275*2d9fd380Sjfb8856606 
276*2d9fd380Sjfb8856606 /*
277*2d9fd380Sjfb8856606  * Insert data into the binary blob at the given offset.
278*2d9fd380Sjfb8856606  *
279*2d9fd380Sjfb8856606  * blob [in] The blob that data is added to.  The blob must
280*2d9fd380Sjfb8856606  * be initialized prior to pushing data.
281*2d9fd380Sjfb8856606  *
282*2d9fd380Sjfb8856606  * offset [in] The offset where the data needs to be inserted.
283*2d9fd380Sjfb8856606  *
284*2d9fd380Sjfb8856606  * data [in/out] A pointer to bytes to be added to the blob.
285*2d9fd380Sjfb8856606  *
286*2d9fd380Sjfb8856606  * datalen [in] The number of bits to be added to the blob.
287*2d9fd380Sjfb8856606  *
288*2d9fd380Sjfb8856606  * The offset of the data is updated after each push of data.
289*2d9fd380Sjfb8856606  * NULL returned on error.
290*2d9fd380Sjfb8856606  */
291*2d9fd380Sjfb8856606 uint32_t
ulp_blob_insert(struct ulp_blob * blob,uint32_t offset,uint8_t * data,uint32_t datalen)292*2d9fd380Sjfb8856606 ulp_blob_insert(struct ulp_blob *blob, uint32_t offset,
293*2d9fd380Sjfb8856606 		uint8_t *data, uint32_t datalen)
294*2d9fd380Sjfb8856606 {
295*2d9fd380Sjfb8856606 	uint32_t rc;
296*2d9fd380Sjfb8856606 	uint8_t local_data[BNXT_ULP_FLMP_BLOB_SIZE];
297*2d9fd380Sjfb8856606 	uint16_t mov_len;
298*2d9fd380Sjfb8856606 
299*2d9fd380Sjfb8856606 	/* validate the arguments */
300*2d9fd380Sjfb8856606 	if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx) ||
301*2d9fd380Sjfb8856606 	    offset > blob->write_idx) {
302*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
303*2d9fd380Sjfb8856606 		return 0; /* failure */
304*2d9fd380Sjfb8856606 	}
305*2d9fd380Sjfb8856606 
306*2d9fd380Sjfb8856606 	mov_len = blob->write_idx - offset;
307*2d9fd380Sjfb8856606 	/* If offset and data len are not 8 bit aligned then return error */
308*2d9fd380Sjfb8856606 	if (ULP_BITS_IS_BYTE_NOT_ALIGNED(offset) ||
309*2d9fd380Sjfb8856606 	    ULP_BITS_IS_BYTE_NOT_ALIGNED(datalen)) {
310*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument, not aligned\n");
311*2d9fd380Sjfb8856606 		return 0; /* failure */
312*2d9fd380Sjfb8856606 	}
313*2d9fd380Sjfb8856606 
314*2d9fd380Sjfb8856606 	/* copy the data so we can move the data */
315*2d9fd380Sjfb8856606 	memcpy(local_data, &blob->data[ULP_BITS_2_BYTE_NR(offset)],
316*2d9fd380Sjfb8856606 	       ULP_BITS_2_BYTE(mov_len));
317*2d9fd380Sjfb8856606 	blob->write_idx = offset;
318*2d9fd380Sjfb8856606 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
319*2d9fd380Sjfb8856606 		rc = ulp_bs_push_msb(blob->data,
320*2d9fd380Sjfb8856606 				     blob->write_idx,
321*2d9fd380Sjfb8856606 				     datalen,
322*2d9fd380Sjfb8856606 				     data);
323*2d9fd380Sjfb8856606 	else
324*2d9fd380Sjfb8856606 		rc = ulp_bs_push_lsb(blob->data,
325*2d9fd380Sjfb8856606 				     blob->write_idx,
326*2d9fd380Sjfb8856606 				     datalen,
327*2d9fd380Sjfb8856606 				     data);
328*2d9fd380Sjfb8856606 	if (!rc) {
329*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "Failed ro write blob\n");
330*2d9fd380Sjfb8856606 		return 0;
331*2d9fd380Sjfb8856606 	}
332*2d9fd380Sjfb8856606 	/* copy the previously stored data */
333*2d9fd380Sjfb8856606 	memcpy(&blob->data[ULP_BITS_2_BYTE_NR(offset + datalen)], local_data,
334*2d9fd380Sjfb8856606 	       ULP_BITS_2_BYTE(mov_len));
335*2d9fd380Sjfb8856606 	blob->write_idx += (mov_len + datalen);
336*2d9fd380Sjfb8856606 	return datalen;
337*2d9fd380Sjfb8856606 }
338*2d9fd380Sjfb8856606 
339*2d9fd380Sjfb8856606 /*
340*2d9fd380Sjfb8856606  * Add data to the binary blob at the current offset.
341*2d9fd380Sjfb8856606  *
342*2d9fd380Sjfb8856606  * blob [in] The blob that data is added to.  The blob must
343*2d9fd380Sjfb8856606  * be initialized prior to pushing data.
344*2d9fd380Sjfb8856606  *
345*2d9fd380Sjfb8856606  * data [in] 64-bit value to be added to the blob.
346*2d9fd380Sjfb8856606  *
347*2d9fd380Sjfb8856606  * datalen [in] The number of bits to be added to the blob.
348*2d9fd380Sjfb8856606  *
349*2d9fd380Sjfb8856606  * The offset of the data is updated after each push of data.
350*2d9fd380Sjfb8856606  * NULL returned on error, pointer pushed value otherwise.
351*2d9fd380Sjfb8856606  */
352*2d9fd380Sjfb8856606 uint8_t *
ulp_blob_push_64(struct ulp_blob * blob,uint64_t * data,uint32_t datalen)353*2d9fd380Sjfb8856606 ulp_blob_push_64(struct ulp_blob *blob,
354*2d9fd380Sjfb8856606 		 uint64_t *data,
355*2d9fd380Sjfb8856606 		 uint32_t datalen)
356*2d9fd380Sjfb8856606 {
357*2d9fd380Sjfb8856606 	uint8_t *val = (uint8_t *)data;
358*2d9fd380Sjfb8856606 	int rc;
359*2d9fd380Sjfb8856606 
360*2d9fd380Sjfb8856606 	int size = (datalen + 7) / 8;
361*2d9fd380Sjfb8856606 
362*2d9fd380Sjfb8856606 	if (!blob || !data ||
363*2d9fd380Sjfb8856606 	    datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
364*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
365*2d9fd380Sjfb8856606 		return 0;
366*2d9fd380Sjfb8856606 	}
367*2d9fd380Sjfb8856606 
368*2d9fd380Sjfb8856606 	rc = ulp_blob_push(blob, &val[8 - size], datalen);
369*2d9fd380Sjfb8856606 	if (!rc)
370*2d9fd380Sjfb8856606 		return 0;
371*2d9fd380Sjfb8856606 
372*2d9fd380Sjfb8856606 	return &val[8 - size];
373*2d9fd380Sjfb8856606 }
374*2d9fd380Sjfb8856606 
375*2d9fd380Sjfb8856606 /*
376*2d9fd380Sjfb8856606  * Add data to the binary blob at the current offset.
377*2d9fd380Sjfb8856606  *
378*2d9fd380Sjfb8856606  * blob [in] The blob that data is added to.  The blob must
379*2d9fd380Sjfb8856606  * be initialized prior to pushing data.
380*2d9fd380Sjfb8856606  *
381*2d9fd380Sjfb8856606  * data [in] 32-bit value to be added to the blob.
382*2d9fd380Sjfb8856606  *
383*2d9fd380Sjfb8856606  * datalen [in] The number of bits to be added ot the blob.
384*2d9fd380Sjfb8856606  *
385*2d9fd380Sjfb8856606  * The offset of the data is updated after each push of data.
386*2d9fd380Sjfb8856606  * NULL returned on error, pointer pushed value otherwise.
387*2d9fd380Sjfb8856606  */
388*2d9fd380Sjfb8856606 uint8_t *
ulp_blob_push_32(struct ulp_blob * blob,uint32_t * data,uint32_t datalen)389*2d9fd380Sjfb8856606 ulp_blob_push_32(struct ulp_blob *blob,
390*2d9fd380Sjfb8856606 		 uint32_t *data,
391*2d9fd380Sjfb8856606 		 uint32_t datalen)
392*2d9fd380Sjfb8856606 {
393*2d9fd380Sjfb8856606 	uint8_t *val = (uint8_t *)data;
394*2d9fd380Sjfb8856606 	uint32_t rc;
395*2d9fd380Sjfb8856606 	uint32_t size = ULP_BITS_2_BYTE(datalen);
396*2d9fd380Sjfb8856606 
397*2d9fd380Sjfb8856606 	if (!data || size > sizeof(uint32_t)) {
398*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
399*2d9fd380Sjfb8856606 		return 0;
400*2d9fd380Sjfb8856606 	}
401*2d9fd380Sjfb8856606 
402*2d9fd380Sjfb8856606 	rc = ulp_blob_push(blob, &val[sizeof(uint32_t) - size], datalen);
403*2d9fd380Sjfb8856606 	if (!rc)
404*2d9fd380Sjfb8856606 		return 0;
405*2d9fd380Sjfb8856606 
406*2d9fd380Sjfb8856606 	return &val[sizeof(uint32_t) - size];
407*2d9fd380Sjfb8856606 }
408*2d9fd380Sjfb8856606 
409*2d9fd380Sjfb8856606 /*
410*2d9fd380Sjfb8856606  * Add encap data to the binary blob at the current offset.
411*2d9fd380Sjfb8856606  *
412*2d9fd380Sjfb8856606  * blob [in] The blob that data is added to.  The blob must
413*2d9fd380Sjfb8856606  * be initialized prior to pushing data.
414*2d9fd380Sjfb8856606  *
415*2d9fd380Sjfb8856606  * data [in] value to be added to the blob.
416*2d9fd380Sjfb8856606  *
417*2d9fd380Sjfb8856606  * datalen [in] The number of bits to be added to the blob.
418*2d9fd380Sjfb8856606  *
419*2d9fd380Sjfb8856606  * The offset of the data is updated after each push of data.
420*2d9fd380Sjfb8856606  * NULL returned on error, pointer pushed value otherwise.
421*2d9fd380Sjfb8856606  */
422*2d9fd380Sjfb8856606 uint32_t
ulp_blob_push_encap(struct ulp_blob * blob,uint8_t * data,uint32_t datalen)423*2d9fd380Sjfb8856606 ulp_blob_push_encap(struct ulp_blob *blob,
424*2d9fd380Sjfb8856606 		    uint8_t *data,
425*2d9fd380Sjfb8856606 		    uint32_t datalen)
426*2d9fd380Sjfb8856606 {
427*2d9fd380Sjfb8856606 	uint8_t		*val = (uint8_t *)data;
428*2d9fd380Sjfb8856606 	uint32_t	initial_size, write_size = datalen;
429*2d9fd380Sjfb8856606 	uint32_t	size = 0;
430*2d9fd380Sjfb8856606 
431*2d9fd380Sjfb8856606 	if (!blob || !data ||
432*2d9fd380Sjfb8856606 	    datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
433*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
434*2d9fd380Sjfb8856606 		return 0;
435*2d9fd380Sjfb8856606 	}
436*2d9fd380Sjfb8856606 
437*2d9fd380Sjfb8856606 	initial_size = ULP_BYTE_2_BITS(sizeof(uint64_t)) -
438*2d9fd380Sjfb8856606 	    (blob->write_idx % ULP_BYTE_2_BITS(sizeof(uint64_t)));
439*2d9fd380Sjfb8856606 	while (write_size > 0) {
440*2d9fd380Sjfb8856606 		if (initial_size && write_size > initial_size) {
441*2d9fd380Sjfb8856606 			size = initial_size;
442*2d9fd380Sjfb8856606 			initial_size = 0;
443*2d9fd380Sjfb8856606 		} else if (initial_size && write_size <= initial_size) {
444*2d9fd380Sjfb8856606 			size = write_size;
445*2d9fd380Sjfb8856606 			initial_size = 0;
446*2d9fd380Sjfb8856606 		} else if (write_size > ULP_BYTE_2_BITS(sizeof(uint64_t))) {
447*2d9fd380Sjfb8856606 			size = ULP_BYTE_2_BITS(sizeof(uint64_t));
448*2d9fd380Sjfb8856606 		} else {
449*2d9fd380Sjfb8856606 			size = write_size;
450*2d9fd380Sjfb8856606 		}
451*2d9fd380Sjfb8856606 		if (!ulp_blob_push(blob, val, size)) {
452*2d9fd380Sjfb8856606 			BNXT_TF_DBG(ERR, "push field failed\n");
453*2d9fd380Sjfb8856606 			return 0;
454*2d9fd380Sjfb8856606 		}
455*2d9fd380Sjfb8856606 		val += ULP_BITS_2_BYTE(size);
456*2d9fd380Sjfb8856606 		write_size -= size;
457*2d9fd380Sjfb8856606 	}
458*2d9fd380Sjfb8856606 	return datalen;
459*2d9fd380Sjfb8856606 }
460*2d9fd380Sjfb8856606 
461*2d9fd380Sjfb8856606 /*
462*2d9fd380Sjfb8856606  * Adds pad to an initialized blob at the current offset
463*2d9fd380Sjfb8856606  *
464*2d9fd380Sjfb8856606  * blob [in] The blob that data is added to.  The blob must
465*2d9fd380Sjfb8856606  * be initialized prior to pushing data.
466*2d9fd380Sjfb8856606  *
467*2d9fd380Sjfb8856606  * datalen [in] The number of bits of pad to add
468*2d9fd380Sjfb8856606  *
469*2d9fd380Sjfb8856606  * returns the number of pad bits added, -1 on failure
470*2d9fd380Sjfb8856606  */
471*2d9fd380Sjfb8856606 int32_t
ulp_blob_pad_push(struct ulp_blob * blob,uint32_t datalen)472*2d9fd380Sjfb8856606 ulp_blob_pad_push(struct ulp_blob *blob,
473*2d9fd380Sjfb8856606 		  uint32_t datalen)
474*2d9fd380Sjfb8856606 {
475*2d9fd380Sjfb8856606 	if (datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
476*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "Pad too large for blob\n");
477*2d9fd380Sjfb8856606 		return 0;
478*2d9fd380Sjfb8856606 	}
479*2d9fd380Sjfb8856606 
480*2d9fd380Sjfb8856606 	blob->write_idx += datalen;
481*2d9fd380Sjfb8856606 	return datalen;
482*2d9fd380Sjfb8856606 }
483*2d9fd380Sjfb8856606 
484*2d9fd380Sjfb8856606 /* Get data from src and put into dst using little-endian format */
485*2d9fd380Sjfb8856606 static void
ulp_bs_get_lsb(uint8_t * src,uint16_t bitpos,uint8_t bitlen,uint8_t * dst)486*2d9fd380Sjfb8856606 ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
487*2d9fd380Sjfb8856606 {
488*2d9fd380Sjfb8856606 	uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
489*2d9fd380Sjfb8856606 	uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
490*2d9fd380Sjfb8856606 	uint8_t mask, partial, shift;
491*2d9fd380Sjfb8856606 
492*2d9fd380Sjfb8856606 	shift = bitoffs;
493*2d9fd380Sjfb8856606 	partial = ULP_BLOB_BYTE - bitoffs;
494*2d9fd380Sjfb8856606 	if (bitoffs + bitlen <= ULP_BLOB_BYTE) {
495*2d9fd380Sjfb8856606 		mask = ((1 << bitlen) - 1) << shift;
496*2d9fd380Sjfb8856606 		*dst = (src[index] & mask) >> shift;
497*2d9fd380Sjfb8856606 	} else {
498*2d9fd380Sjfb8856606 		mask = ((1 << partial) - 1) << shift;
499*2d9fd380Sjfb8856606 		*dst = (src[index] & mask) >> shift;
500*2d9fd380Sjfb8856606 		index++;
501*2d9fd380Sjfb8856606 		partial = bitlen - partial;
502*2d9fd380Sjfb8856606 		mask = ((1 << partial) - 1);
503*2d9fd380Sjfb8856606 		*dst |= (src[index] & mask) << (ULP_BLOB_BYTE - bitoffs);
504*2d9fd380Sjfb8856606 	}
505*2d9fd380Sjfb8856606 }
506*2d9fd380Sjfb8856606 
507*2d9fd380Sjfb8856606 /* Assuming that src is in little-Endian Format */
508*2d9fd380Sjfb8856606 static void
ulp_bs_pull_lsb(uint8_t * src,uint8_t * dst,uint32_t size,uint32_t offset,uint32_t len)509*2d9fd380Sjfb8856606 ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size,
510*2d9fd380Sjfb8856606 		uint32_t offset, uint32_t len)
511*2d9fd380Sjfb8856606 {
512*2d9fd380Sjfb8856606 	uint32_t idx;
513*2d9fd380Sjfb8856606 	uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
514*2d9fd380Sjfb8856606 
515*2d9fd380Sjfb8856606 	/* iterate bytewise to get data */
516*2d9fd380Sjfb8856606 	for (idx = 0; idx < cnt; idx++) {
517*2d9fd380Sjfb8856606 		ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE,
518*2d9fd380Sjfb8856606 			       &dst[size - 1 - idx]);
519*2d9fd380Sjfb8856606 		offset += ULP_BLOB_BYTE;
520*2d9fd380Sjfb8856606 		len -= ULP_BLOB_BYTE;
521*2d9fd380Sjfb8856606 	}
522*2d9fd380Sjfb8856606 
523*2d9fd380Sjfb8856606 	/* Extract the last reminder data that is not 8 byte boundary */
524*2d9fd380Sjfb8856606 	if (len)
525*2d9fd380Sjfb8856606 		ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]);
526*2d9fd380Sjfb8856606 }
527*2d9fd380Sjfb8856606 
528*2d9fd380Sjfb8856606 /*
529*2d9fd380Sjfb8856606  * Extract data from the binary blob using given offset.
530*2d9fd380Sjfb8856606  *
531*2d9fd380Sjfb8856606  * blob [in] The blob that data is extracted from. The blob must
532*2d9fd380Sjfb8856606  * be initialized prior to pulling data.
533*2d9fd380Sjfb8856606  *
534*2d9fd380Sjfb8856606  * data [in] A pointer to put the data.
535*2d9fd380Sjfb8856606  * data_size [in] size of the data buffer in bytes.
536*2d9fd380Sjfb8856606  *offset [in] - Offset in the blob to extract the data in bits format.
537*2d9fd380Sjfb8856606  * len [in] The number of bits to be pulled from the blob.
538*2d9fd380Sjfb8856606  *
539*2d9fd380Sjfb8856606  * Output: zero on success, -1 on failure
540*2d9fd380Sjfb8856606  */
541*2d9fd380Sjfb8856606 int32_t
ulp_blob_pull(struct ulp_blob * blob,uint8_t * data,uint32_t data_size,uint16_t offset,uint16_t len)542*2d9fd380Sjfb8856606 ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size,
543*2d9fd380Sjfb8856606 	      uint16_t offset, uint16_t len)
544*2d9fd380Sjfb8856606 {
545*2d9fd380Sjfb8856606 	/* validate the arguments */
546*2d9fd380Sjfb8856606 	if (!blob || (offset + len) > blob->bitlen ||
547*2d9fd380Sjfb8856606 	    ULP_BYTE_2_BITS(data_size) < len) {
548*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
549*2d9fd380Sjfb8856606 		return -1; /* failure */
550*2d9fd380Sjfb8856606 	}
551*2d9fd380Sjfb8856606 
552*2d9fd380Sjfb8856606 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) {
553*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "Big endian pull not implemented\n");
554*2d9fd380Sjfb8856606 		return -1; /* failure */
555*2d9fd380Sjfb8856606 	}
556*2d9fd380Sjfb8856606 	ulp_bs_pull_lsb(blob->data, data, data_size, offset, len);
557*2d9fd380Sjfb8856606 	return 0;
558*2d9fd380Sjfb8856606 }
559*2d9fd380Sjfb8856606 
560*2d9fd380Sjfb8856606 /*
561*2d9fd380Sjfb8856606  * Get the data portion of the binary blob.
562*2d9fd380Sjfb8856606  *
563*2d9fd380Sjfb8856606  * blob [in] The blob's data to be retrieved. The blob must be
564*2d9fd380Sjfb8856606  * initialized prior to pushing data.
565*2d9fd380Sjfb8856606  *
566*2d9fd380Sjfb8856606  * datalen [out] The number of bits to that are filled.
567*2d9fd380Sjfb8856606  *
568*2d9fd380Sjfb8856606  * returns a byte array of the blob data.  Returns NULL on error.
569*2d9fd380Sjfb8856606  */
570*2d9fd380Sjfb8856606 uint8_t *
ulp_blob_data_get(struct ulp_blob * blob,uint16_t * datalen)571*2d9fd380Sjfb8856606 ulp_blob_data_get(struct ulp_blob *blob,
572*2d9fd380Sjfb8856606 		  uint16_t *datalen)
573*2d9fd380Sjfb8856606 {
574*2d9fd380Sjfb8856606 	/* validate the arguments */
575*2d9fd380Sjfb8856606 	if (!blob) {
576*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
577*2d9fd380Sjfb8856606 		return NULL; /* failure */
578*2d9fd380Sjfb8856606 	}
579*2d9fd380Sjfb8856606 	*datalen = blob->write_idx;
580*2d9fd380Sjfb8856606 	return blob->data;
581*2d9fd380Sjfb8856606 }
582*2d9fd380Sjfb8856606 
583*2d9fd380Sjfb8856606 /*
584*2d9fd380Sjfb8856606  * Set the encap swap start index of the binary blob.
585*2d9fd380Sjfb8856606  *
586*2d9fd380Sjfb8856606  * blob [in] The blob's data to be retrieved. The blob must be
587*2d9fd380Sjfb8856606  * initialized prior to pushing data.
588*2d9fd380Sjfb8856606  *
589*2d9fd380Sjfb8856606  * returns void.
590*2d9fd380Sjfb8856606  */
591*2d9fd380Sjfb8856606 void
ulp_blob_encap_swap_idx_set(struct ulp_blob * blob)592*2d9fd380Sjfb8856606 ulp_blob_encap_swap_idx_set(struct ulp_blob *blob)
593*2d9fd380Sjfb8856606 {
594*2d9fd380Sjfb8856606 	/* validate the arguments */
595*2d9fd380Sjfb8856606 	if (!blob) {
596*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
597*2d9fd380Sjfb8856606 		return; /* failure */
598*2d9fd380Sjfb8856606 	}
599*2d9fd380Sjfb8856606 	blob->encap_swap_idx = blob->write_idx;
600*2d9fd380Sjfb8856606 }
601*2d9fd380Sjfb8856606 
602*2d9fd380Sjfb8856606 /*
603*2d9fd380Sjfb8856606  * Perform the encap buffer swap to 64 bit reversal.
604*2d9fd380Sjfb8856606  *
605*2d9fd380Sjfb8856606  * blob [in] The blob's data to be used for swap.
606*2d9fd380Sjfb8856606  *
607*2d9fd380Sjfb8856606  * returns void.
608*2d9fd380Sjfb8856606  */
609*2d9fd380Sjfb8856606 void
ulp_blob_perform_encap_swap(struct ulp_blob * blob)610*2d9fd380Sjfb8856606 ulp_blob_perform_encap_swap(struct ulp_blob *blob)
611*2d9fd380Sjfb8856606 {
612*2d9fd380Sjfb8856606 	uint32_t i, idx = 0, end_idx = 0, roundoff;
613*2d9fd380Sjfb8856606 	uint8_t temp_val_1, temp_val_2;
614*2d9fd380Sjfb8856606 
615*2d9fd380Sjfb8856606 	/* validate the arguments */
616*2d9fd380Sjfb8856606 	if (!blob) {
617*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
618*2d9fd380Sjfb8856606 		return; /* failure */
619*2d9fd380Sjfb8856606 	}
620*2d9fd380Sjfb8856606 	idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx);
621*2d9fd380Sjfb8856606 	end_idx = ULP_BITS_2_BYTE(blob->write_idx);
622*2d9fd380Sjfb8856606 	roundoff = ULP_BYTE_2_BITS(ULP_BITS_2_BYTE(end_idx));
623*2d9fd380Sjfb8856606 	if (roundoff > end_idx) {
624*2d9fd380Sjfb8856606 		blob->write_idx += ULP_BYTE_2_BITS(roundoff - end_idx);
625*2d9fd380Sjfb8856606 		end_idx = roundoff;
626*2d9fd380Sjfb8856606 	}
627*2d9fd380Sjfb8856606 	while (idx <= end_idx) {
628*2d9fd380Sjfb8856606 		for (i = 0; i < 4; i = i + 2) {
629*2d9fd380Sjfb8856606 			temp_val_1 = blob->data[idx + i];
630*2d9fd380Sjfb8856606 			temp_val_2 = blob->data[idx + i + 1];
631*2d9fd380Sjfb8856606 			blob->data[idx + i] = blob->data[idx + 6 - i];
632*2d9fd380Sjfb8856606 			blob->data[idx + i + 1] = blob->data[idx + 7 - i];
633*2d9fd380Sjfb8856606 			blob->data[idx + 7 - i] = temp_val_2;
634*2d9fd380Sjfb8856606 			blob->data[idx + 6 - i] = temp_val_1;
635*2d9fd380Sjfb8856606 		}
636*2d9fd380Sjfb8856606 		idx += 8;
637*2d9fd380Sjfb8856606 	}
638*2d9fd380Sjfb8856606 }
639*2d9fd380Sjfb8856606 
640*2d9fd380Sjfb8856606 /*
641*2d9fd380Sjfb8856606  * Perform the blob buffer reversal byte wise.
642*2d9fd380Sjfb8856606  * This api makes the first byte the last and
643*2d9fd380Sjfb8856606  * vice-versa.
644*2d9fd380Sjfb8856606  *
645*2d9fd380Sjfb8856606  * blob [in] The blob's data to be used for swap.
646*2d9fd380Sjfb8856606  *
647*2d9fd380Sjfb8856606  * returns void.
648*2d9fd380Sjfb8856606  */
649*2d9fd380Sjfb8856606 void
ulp_blob_perform_byte_reverse(struct ulp_blob * blob)650*2d9fd380Sjfb8856606 ulp_blob_perform_byte_reverse(struct ulp_blob *blob)
651*2d9fd380Sjfb8856606 {
652*2d9fd380Sjfb8856606 	uint32_t idx = 0, num = 0;
653*2d9fd380Sjfb8856606 	uint8_t xchar;
654*2d9fd380Sjfb8856606 
655*2d9fd380Sjfb8856606 	/* validate the arguments */
656*2d9fd380Sjfb8856606 	if (!blob) {
657*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
658*2d9fd380Sjfb8856606 		return; /* failure */
659*2d9fd380Sjfb8856606 	}
660*2d9fd380Sjfb8856606 
661*2d9fd380Sjfb8856606 	num = ULP_BITS_2_BYTE_NR(blob->write_idx);
662*2d9fd380Sjfb8856606 	for (idx = 0; idx < (num / 2); idx++) {
663*2d9fd380Sjfb8856606 		xchar = blob->data[idx];
664*2d9fd380Sjfb8856606 		blob->data[idx] = blob->data[(num - 1) - idx];
665*2d9fd380Sjfb8856606 		blob->data[(num - 1) - idx] = xchar;
666*2d9fd380Sjfb8856606 	}
667*2d9fd380Sjfb8856606 }
668*2d9fd380Sjfb8856606 
669*2d9fd380Sjfb8856606 /*
670*2d9fd380Sjfb8856606  * Perform the blob buffer 64 bit word swap.
671*2d9fd380Sjfb8856606  * This api makes the first 4 bytes the last in
672*2d9fd380Sjfb8856606  * a given 64 bit value and vice-versa.
673*2d9fd380Sjfb8856606  *
674*2d9fd380Sjfb8856606  * blob [in] The blob's data to be used for swap.
675*2d9fd380Sjfb8856606  *
676*2d9fd380Sjfb8856606  * returns void.
677*2d9fd380Sjfb8856606  */
678*2d9fd380Sjfb8856606 void
ulp_blob_perform_64B_word_swap(struct ulp_blob * blob)679*2d9fd380Sjfb8856606 ulp_blob_perform_64B_word_swap(struct ulp_blob *blob)
680*2d9fd380Sjfb8856606 {
681*2d9fd380Sjfb8856606 	uint32_t i, j, num;
682*2d9fd380Sjfb8856606 	uint8_t xchar;
683*2d9fd380Sjfb8856606 	uint32_t word_size = ULP_64B_IN_BYTES / 2;
684*2d9fd380Sjfb8856606 
685*2d9fd380Sjfb8856606 	/* validate the arguments */
686*2d9fd380Sjfb8856606 	if (!blob) {
687*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
688*2d9fd380Sjfb8856606 		return; /* failure */
689*2d9fd380Sjfb8856606 	}
690*2d9fd380Sjfb8856606 	num = ULP_BITS_2_BYTE(blob->write_idx);
691*2d9fd380Sjfb8856606 	for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
692*2d9fd380Sjfb8856606 		for (j = 0; j < word_size; j++) {
693*2d9fd380Sjfb8856606 			xchar = blob->data[i + j];
694*2d9fd380Sjfb8856606 			blob->data[i + j] = blob->data[i + j + word_size];
695*2d9fd380Sjfb8856606 			blob->data[i + j + word_size] = xchar;
696*2d9fd380Sjfb8856606 		}
697*2d9fd380Sjfb8856606 	}
698*2d9fd380Sjfb8856606 }
699*2d9fd380Sjfb8856606 
700*2d9fd380Sjfb8856606 /*
701*2d9fd380Sjfb8856606  * Perform the blob buffer 64 bit byte swap.
702*2d9fd380Sjfb8856606  * This api makes the first byte the last in
703*2d9fd380Sjfb8856606  * a given 64 bit value and vice-versa.
704*2d9fd380Sjfb8856606  *
705*2d9fd380Sjfb8856606  * blob [in] The blob's data to be used for swap.
706*2d9fd380Sjfb8856606  *
707*2d9fd380Sjfb8856606  * returns void.
708*2d9fd380Sjfb8856606  */
709*2d9fd380Sjfb8856606 void
ulp_blob_perform_64B_byte_swap(struct ulp_blob * blob)710*2d9fd380Sjfb8856606 ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob)
711*2d9fd380Sjfb8856606 {
712*2d9fd380Sjfb8856606 	uint32_t i, j, num;
713*2d9fd380Sjfb8856606 	uint8_t xchar;
714*2d9fd380Sjfb8856606 	uint32_t offset = ULP_64B_IN_BYTES - 1;
715*2d9fd380Sjfb8856606 
716*2d9fd380Sjfb8856606 	/* validate the arguments */
717*2d9fd380Sjfb8856606 	if (!blob) {
718*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
719*2d9fd380Sjfb8856606 		return; /* failure */
720*2d9fd380Sjfb8856606 	}
721*2d9fd380Sjfb8856606 	num = ULP_BITS_2_BYTE(blob->write_idx);
722*2d9fd380Sjfb8856606 	for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
723*2d9fd380Sjfb8856606 		for (j = 0; j < (ULP_64B_IN_BYTES / 2); j++) {
724*2d9fd380Sjfb8856606 			xchar = blob->data[i + j];
725*2d9fd380Sjfb8856606 			blob->data[i + j] = blob->data[i + offset - j];
726*2d9fd380Sjfb8856606 			blob->data[i + offset - j] = xchar;
727*2d9fd380Sjfb8856606 		}
728*2d9fd380Sjfb8856606 	}
729*2d9fd380Sjfb8856606 }
730*2d9fd380Sjfb8856606 
731*2d9fd380Sjfb8856606 /*
732*2d9fd380Sjfb8856606  * Read data from the operand
733*2d9fd380Sjfb8856606  *
734*2d9fd380Sjfb8856606  * operand [in] A pointer to a 16 Byte operand
735*2d9fd380Sjfb8856606  *
736*2d9fd380Sjfb8856606  * val [in/out] The variable to copy the operand to
737*2d9fd380Sjfb8856606  *
738*2d9fd380Sjfb8856606  * bytes [in] The number of bytes to read into val
739*2d9fd380Sjfb8856606  *
740*2d9fd380Sjfb8856606  * returns number of bits read, zero on error
741*2d9fd380Sjfb8856606  */
742*2d9fd380Sjfb8856606 uint16_t
ulp_operand_read(uint8_t * operand,uint8_t * val,uint16_t bytes)743*2d9fd380Sjfb8856606 ulp_operand_read(uint8_t *operand,
744*2d9fd380Sjfb8856606 		 uint8_t *val,
745*2d9fd380Sjfb8856606 		 uint16_t bytes)
746*2d9fd380Sjfb8856606 {
747*2d9fd380Sjfb8856606 	/* validate the arguments */
748*2d9fd380Sjfb8856606 	if (!operand || !val) {
749*2d9fd380Sjfb8856606 		BNXT_TF_DBG(ERR, "invalid argument\n");
750*2d9fd380Sjfb8856606 		return 0; /* failure */
751*2d9fd380Sjfb8856606 	}
752*2d9fd380Sjfb8856606 	memcpy(val, operand, bytes);
753*2d9fd380Sjfb8856606 	return bytes;
754*2d9fd380Sjfb8856606 }
755*2d9fd380Sjfb8856606 
756*2d9fd380Sjfb8856606 /*
757*2d9fd380Sjfb8856606  * copy the buffer in the encap format which is 2 bytes.
758*2d9fd380Sjfb8856606  * The MSB of the src is placed at the LSB of dst.
759*2d9fd380Sjfb8856606  *
760*2d9fd380Sjfb8856606  * dst [out] The destination buffer
761*2d9fd380Sjfb8856606  * src [in] The source buffer dst
762*2d9fd380Sjfb8856606  * size[in] size of the buffer.
763*2d9fd380Sjfb8856606  * align[in] The alignment is either 8 or 16.
764*2d9fd380Sjfb8856606  */
765*2d9fd380Sjfb8856606 void
ulp_encap_buffer_copy(uint8_t * dst,const uint8_t * src,uint16_t size,uint16_t align)766*2d9fd380Sjfb8856606 ulp_encap_buffer_copy(uint8_t *dst,
767*2d9fd380Sjfb8856606 		      const uint8_t *src,
768*2d9fd380Sjfb8856606 		      uint16_t size,
769*2d9fd380Sjfb8856606 		      uint16_t align)
770*2d9fd380Sjfb8856606 {
771*2d9fd380Sjfb8856606 	uint16_t	idx, tmp_size = 0;
772*2d9fd380Sjfb8856606 
773*2d9fd380Sjfb8856606 	do {
774*2d9fd380Sjfb8856606 		dst += tmp_size;
775*2d9fd380Sjfb8856606 		src += tmp_size;
776*2d9fd380Sjfb8856606 		idx = 0;
777*2d9fd380Sjfb8856606 		if (size > align) {
778*2d9fd380Sjfb8856606 			tmp_size = align;
779*2d9fd380Sjfb8856606 			size -= align;
780*2d9fd380Sjfb8856606 		} else {
781*2d9fd380Sjfb8856606 			tmp_size = size;
782*2d9fd380Sjfb8856606 			size = 0;
783*2d9fd380Sjfb8856606 		}
784*2d9fd380Sjfb8856606 		/* copy 2 bytes at a time. Write MSB to LSB */
785*2d9fd380Sjfb8856606 		while ((idx + sizeof(uint16_t)) <= tmp_size) {
786*2d9fd380Sjfb8856606 			memcpy(&dst[idx],
787*2d9fd380Sjfb8856606 			       &src[tmp_size - idx - sizeof(uint16_t)],
788*2d9fd380Sjfb8856606 			       sizeof(uint16_t));
789*2d9fd380Sjfb8856606 			idx += sizeof(uint16_t);
790*2d9fd380Sjfb8856606 		}
791*2d9fd380Sjfb8856606 	} while (size);
792*2d9fd380Sjfb8856606 }
793*2d9fd380Sjfb8856606 
794*2d9fd380Sjfb8856606 /*
795*2d9fd380Sjfb8856606  * Check the buffer is empty
796*2d9fd380Sjfb8856606  *
797*2d9fd380Sjfb8856606  * buf [in] The buffer
798*2d9fd380Sjfb8856606  * size [in] The size of the buffer
799*2d9fd380Sjfb8856606  *
800*2d9fd380Sjfb8856606  */
ulp_buffer_is_empty(const uint8_t * buf,uint32_t size)801*2d9fd380Sjfb8856606 int32_t ulp_buffer_is_empty(const uint8_t *buf, uint32_t size)
802*2d9fd380Sjfb8856606 {
803*2d9fd380Sjfb8856606 	return buf[0] == 0 && !memcmp(buf, buf + 1, size - 1);
804*2d9fd380Sjfb8856606 }
805*2d9fd380Sjfb8856606 
806*2d9fd380Sjfb8856606 /* Function to check if bitmap is zero.Return 1 on success */
ulp_bitmap_is_zero(uint8_t * bitmap,int32_t size)807*2d9fd380Sjfb8856606 uint32_t ulp_bitmap_is_zero(uint8_t *bitmap, int32_t size)
808*2d9fd380Sjfb8856606 {
809*2d9fd380Sjfb8856606 	while (size-- > 0) {
810*2d9fd380Sjfb8856606 		if (*bitmap != 0)
811*2d9fd380Sjfb8856606 			return 0;
812*2d9fd380Sjfb8856606 		bitmap++;
813*2d9fd380Sjfb8856606 	}
814*2d9fd380Sjfb8856606 	return 1;
815*2d9fd380Sjfb8856606 }
816*2d9fd380Sjfb8856606 
817*2d9fd380Sjfb8856606 /* Function to check if bitmap is ones. Return 1 on success */
ulp_bitmap_is_ones(uint8_t * bitmap,int32_t size)818*2d9fd380Sjfb8856606 uint32_t ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size)
819*2d9fd380Sjfb8856606 {
820*2d9fd380Sjfb8856606 	while (size-- > 0) {
821*2d9fd380Sjfb8856606 		if (*bitmap != 0xFF)
822*2d9fd380Sjfb8856606 			return 0;
823*2d9fd380Sjfb8856606 		bitmap++;
824*2d9fd380Sjfb8856606 	}
825*2d9fd380Sjfb8856606 	return 1;
826*2d9fd380Sjfb8856606 }
827*2d9fd380Sjfb8856606 
828*2d9fd380Sjfb8856606 /* Function to check if bitmap is not zero. Return 1 on success */
ulp_bitmap_notzero(uint8_t * bitmap,int32_t size)829*2d9fd380Sjfb8856606 uint32_t ulp_bitmap_notzero(uint8_t *bitmap, int32_t size)
830*2d9fd380Sjfb8856606 {
831*2d9fd380Sjfb8856606 	while (size-- > 0) {
832*2d9fd380Sjfb8856606 		if (*bitmap != 0)
833*2d9fd380Sjfb8856606 			return 1;
834*2d9fd380Sjfb8856606 		bitmap++;
835*2d9fd380Sjfb8856606 	}
836*2d9fd380Sjfb8856606 	return 0;
837*2d9fd380Sjfb8856606 }
838