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