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