1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2014-2021 Broadcom
6 #include <rte_common.h>
8 #include "bnxt_tf_common.h"
11 * Initialize the regfile structure for writing
13 * regfile [in] Ptr to a regfile instance
15 * returns 0 on error or 1 on success
18 ulp_regfile_init(struct ulp_regfile *regfile)
20 /* validate the arguments */
22 BNXT_TF_DBG(ERR, "invalid argument\n");
23 return 0; /* failure */
25 memset(regfile, 0, sizeof(struct ulp_regfile));
26 return 1; /* Success */
30 * Read a value from the regfile
32 * regfile [in] The regfile instance. Must be initialized prior to being used
34 * field [in] The field to be read within the regfile.
38 * returns size, zero on failure
41 ulp_regfile_read(struct ulp_regfile *regfile,
42 enum bnxt_ulp_rf_idx field,
45 /* validate the arguments */
46 if (!regfile || field >= BNXT_ULP_RF_IDX_LAST) {
47 BNXT_TF_DBG(ERR, "invalid argument\n");
48 return 0; /* failure */
51 *data = regfile->entry[field].data;
56 * Write a value to the regfile
58 * regfile [in] The regfile instance. Must be initialized prior to being used
60 * field [in] The field to be written within the regfile.
62 * data [in] The value is written into this variable. It is going to be in the
63 * same byte order as it was written.
65 * size [in] The size in bytes of the value being written into this
68 * returns 0 on success
71 ulp_regfile_write(struct ulp_regfile *regfile,
72 enum bnxt_ulp_rf_idx field,
75 /* validate the arguments */
76 if (!regfile || field >= BNXT_ULP_RF_IDX_LAST) {
77 BNXT_TF_DBG(ERR, "invalid argument\n");
78 return -EINVAL; /* failure */
81 regfile->entry[field].data = data;
82 return 0; /* Success */
86 ulp_bs_put_msb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
88 uint8_t bitoffs = bitpos % 8;
89 uint16_t index = bitpos / 8;
95 mask = ((uint8_t)-1 >> (8 - bitlen));
96 shift = 8 - bitoffs - bitlen;
100 tmp &= ~(mask << shift);
104 tmp &= ~((uint8_t)-1 >> bitoffs);
105 tmp |= val >> -shift;
109 tmp &= ((uint8_t)-1 >> (bitlen - (8 - bitoffs)));
110 tmp |= val << (8 + shift);
116 ulp_bs_put_lsb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
118 uint8_t bitoffs = bitpos % 8;
119 uint16_t index = bitpos / 8;
128 if (bitoffs + bitlen <= 8) {
129 mask = ((1 << bitlen) - 1) << shift;
131 tmp |= ((val << shift) & mask);
134 partial = 8 - bitoffs;
135 mask = ((1 << partial) - 1) << shift;
137 tmp |= ((val << shift) & mask);
141 partial = bitlen - partial;
142 mask = ((1 << partial) - 1);
151 * Add data to the byte array in Little endian format.
153 * bs [in] The byte array where data is pushed
155 * pos [in] The offset where data is pushed
157 * len [in] The number of bits to be added to the data array.
159 * val [in] The data to be added to the data array.
161 * returns the number of bits pushed.
164 ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
170 if (cnt > 0 && !(len % 8))
173 for (i = 0; i < cnt; i++) {
174 ulp_bs_put_lsb(bs, pos, 8, val[cnt - i]);
179 /* Handle the remainder bits */
181 ulp_bs_put_lsb(bs, pos, tlen, val[0]);
186 * Add data to the byte array in Big endian format.
188 * bs [in] The byte array where data is pushed
190 * pos [in] The offset where data is pushed
192 * len [in] The number of bits to be added to the data array.
194 * val [in] The data to be added to the data array.
196 * returns the number of bits pushed.
199 ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
202 int cnt = (len + 7) / 8;
205 /* Handle any remainder bits */
211 ulp_bs_put_msb(bs, pos, tmp, val[0]);
216 for (i = 1; i < cnt; i++) {
217 ulp_bs_put_msb(bs, pos, 8, val[i]);
226 * Initializes the blob structure for creating binary blob
228 * blob [in] The blob to be initialized
230 * bitlen [in] The bit length of the blob
232 * order [in] The byte order for the blob. Currently only supporting
233 * big endian. All fields are packed with this order.
235 * returns 0 on error or 1 on success
236 * Notes - If bitlen is zero then set it to max.
239 ulp_blob_init(struct ulp_blob *blob,
241 enum bnxt_ulp_byte_order order)
243 /* validate the arguments */
244 if (!blob || bitlen > (8 * sizeof(blob->data))) {
245 BNXT_TF_DBG(ERR, "invalid argument\n");
246 return 0; /* failure */
249 blob->bitlen = bitlen;
251 blob->bitlen = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
252 blob->byte_order = order;
254 memset(blob->data, 0, sizeof(blob->data));
255 return 1; /* Success */
259 * Add data to the binary blob at the current offset.
261 * blob [in] The blob that data is added to. The blob must
262 * be initialized prior to pushing data.
264 * data [in] A pointer to bytes to be added to the blob.
266 * datalen [in] The number of bits to be added to the blob.
268 * The offset of the data is updated after each push of data.
269 * NULL returned on error.
271 #define ULP_BLOB_BYTE 8
272 #define ULP_BLOB_BYTE_HEX 0xFF
273 #define BLOB_MASK_CAL(x) ((0xFF << (x)) & 0xFF)
275 ulp_blob_push(struct ulp_blob *blob,
281 /* validate the arguments */
282 if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
283 BNXT_TF_DBG(ERR, "invalid argument\n");
284 return 0; /* failure */
287 if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
288 rc = ulp_bs_push_msb(blob->data,
293 rc = ulp_bs_push_lsb(blob->data,
298 BNXT_TF_DBG(ERR, "Failed to write blob\n");
301 blob->write_idx += datalen;
306 * Insert data into the binary blob at the given offset.
308 * blob [in] The blob that data is added to. The blob must
309 * be initialized prior to pushing data.
311 * offset [in] The offset where the data needs to be inserted.
313 * data [in/out] A pointer to bytes to be added to the blob.
315 * datalen [in] The number of bits to be added to the blob.
317 * The offset of the data is updated after each push of data.
318 * NULL returned on error.
321 ulp_blob_insert(struct ulp_blob *blob, uint32_t offset,
322 uint8_t *data, uint32_t datalen)
325 uint8_t local_data[BNXT_ULP_FLMP_BLOB_SIZE];
328 /* validate the arguments */
329 if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx) ||
330 offset > blob->write_idx) {
331 BNXT_TF_DBG(ERR, "invalid argument\n");
332 return 0; /* failure */
335 mov_len = blob->write_idx - offset;
336 /* If offset and data len are not 8 bit aligned then return error */
337 if (ULP_BITS_IS_BYTE_NOT_ALIGNED(offset) ||
338 ULP_BITS_IS_BYTE_NOT_ALIGNED(datalen)) {
339 BNXT_TF_DBG(ERR, "invalid argument, not aligned\n");
340 return 0; /* failure */
343 /* copy the data so we can move the data */
344 memcpy(local_data, &blob->data[ULP_BITS_2_BYTE_NR(offset)],
345 ULP_BITS_2_BYTE(mov_len));
346 blob->write_idx = offset;
347 if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
348 rc = ulp_bs_push_msb(blob->data,
353 rc = ulp_bs_push_lsb(blob->data,
358 BNXT_TF_DBG(ERR, "Failed to write blob\n");
361 /* copy the previously stored data */
362 memcpy(&blob->data[ULP_BITS_2_BYTE_NR(offset + datalen)], local_data,
363 ULP_BITS_2_BYTE(mov_len));
364 blob->write_idx += (mov_len + datalen);
369 * Add data to the binary blob at the current offset.
371 * blob [in] The blob that data is added to. The blob must
372 * be initialized prior to pushing data.
374 * data [in] 64-bit value to be added to the blob.
376 * datalen [in] The number of bits to be added to the blob.
378 * The offset of the data is updated after each push of data.
379 * NULL returned on error, pointer pushed value otherwise.
382 ulp_blob_push_64(struct ulp_blob *blob,
386 uint8_t *val = (uint8_t *)data;
389 int size = (datalen + 7) / 8;
391 if (!blob || !data ||
392 datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
393 BNXT_TF_DBG(ERR, "invalid argument\n");
397 rc = ulp_blob_push(blob, &val[8 - size], datalen);
401 return &val[8 - size];
405 * Add data to the binary blob at the current offset.
407 * blob [in] The blob that data is added to. The blob must
408 * be initialized prior to pushing data.
410 * data [in] 32-bit value to be added to the blob.
412 * datalen [in] The number of bits to be added to the blob.
414 * The offset of the data is updated after each push of data.
415 * NULL returned on error, pointer pushed value otherwise.
418 ulp_blob_push_32(struct ulp_blob *blob,
422 uint8_t *val = (uint8_t *)data;
424 uint32_t size = ULP_BITS_2_BYTE(datalen);
426 if (!data || size > sizeof(uint32_t)) {
427 BNXT_TF_DBG(ERR, "invalid argument\n");
431 rc = ulp_blob_push(blob, &val[sizeof(uint32_t) - size], datalen);
435 return &val[sizeof(uint32_t) - size];
439 * Add encap data to the binary blob at the current offset.
441 * blob [in] The blob that data is added to. The blob must
442 * be initialized prior to pushing data.
444 * data [in] value to be added to the blob.
446 * datalen [in] The number of bits to be added to the blob.
448 * The offset of the data is updated after each push of data.
449 * NULL returned on error, pointer pushed value otherwise.
452 ulp_blob_push_encap(struct ulp_blob *blob,
456 uint8_t *val = (uint8_t *)data;
457 uint32_t initial_size, write_size = datalen;
460 if (!blob || !data ||
461 datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
462 BNXT_TF_DBG(ERR, "invalid argument\n");
466 initial_size = ULP_BYTE_2_BITS(sizeof(uint64_t)) -
467 (blob->write_idx % ULP_BYTE_2_BITS(sizeof(uint64_t)));
468 while (write_size > 0) {
469 if (initial_size && write_size > initial_size) {
472 } else if (initial_size && write_size <= initial_size) {
475 } else if (write_size > ULP_BYTE_2_BITS(sizeof(uint64_t))) {
476 size = ULP_BYTE_2_BITS(sizeof(uint64_t));
480 if (!ulp_blob_push(blob, val, size)) {
481 BNXT_TF_DBG(ERR, "push field failed\n");
484 val += ULP_BITS_2_BYTE(size);
491 * Adds pad to an initialized blob at the current offset
493 * blob [in] The blob that data is added to. The blob must
494 * be initialized prior to pushing data.
496 * datalen [in] The number of bits of pad to add
498 * returns the number of pad bits added, -1 on failure
501 ulp_blob_pad_push(struct ulp_blob *blob,
504 if (datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
505 BNXT_TF_DBG(ERR, "Pad too large for blob\n");
509 blob->write_idx += datalen;
514 * Adds pad to an initialized blob at the current offset based on
517 * blob [in] The blob that needs to be aligned
519 * align [in] Alignment in bits.
521 * returns the number of pad bits added, -1 on failure
524 ulp_blob_pad_align(struct ulp_blob *blob,
529 pad = RTE_ALIGN(blob->write_idx, align) - blob->write_idx;
530 if (pad > (int32_t)(blob->bitlen - blob->write_idx)) {
531 BNXT_TF_DBG(ERR, "Pad too large for blob\n");
534 blob->write_idx += pad;
538 /* Get data from src and put into dst using little-endian format */
540 ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
542 uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
543 uint16_t index = ULP_BITS_2_BYTE_NR(bitpos);
544 uint8_t mask, partial, shift;
547 partial = ULP_BLOB_BYTE - bitoffs;
548 if (bitoffs + bitlen <= ULP_BLOB_BYTE) {
549 mask = ((1 << bitlen) - 1) << shift;
550 *dst = (src[index] & mask) >> shift;
552 mask = ((1 << partial) - 1) << shift;
553 *dst = (src[index] & mask) >> shift;
555 partial = bitlen - partial;
556 mask = ((1 << partial) - 1);
557 *dst |= (src[index] & mask) << (ULP_BLOB_BYTE - bitoffs);
562 * Get data from the byte array in Little endian format.
564 * src [in] The byte array where data is extracted from
566 * dst [out] The byte array where data is pulled into
568 * size [in] The size of dst array in bytes
570 * offset [in] The offset where data is pulled
572 * len [in] The number of bits to be extracted from the data array
577 ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size,
578 uint32_t offset, uint32_t len)
581 uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
583 /* iterate bytewise to get data */
584 for (idx = 0; idx < cnt; idx++) {
585 ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE,
586 &dst[size - 1 - idx]);
587 offset += ULP_BLOB_BYTE;
588 len -= ULP_BLOB_BYTE;
591 /* Extract the last reminder data that is not 8 byte boundary */
593 ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]);
596 /* Get data from src and put into dst using big-endian format */
598 ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
600 uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
601 uint16_t index = ULP_BITS_2_BYTE_NR(bitpos);
605 shift = ULP_BLOB_BYTE - bitoffs - bitlen;
607 mask = 0xFF >> -bitlen;
608 *dst = (src[index] >> shift) & mask;
610 *dst = (src[index] & (0xFF >> bitoffs)) << -shift;
611 *dst |= src[index + 1] >> -shift;
616 * Get data from the byte array in Big endian format.
618 * src [in] The byte array where data is extracted from
620 * dst [out] The byte array where data is pulled into
622 * offset [in] The offset where data is pulled
624 * len [in] The number of bits to be extracted from the data array
629 ulp_bs_pull_msb(uint8_t *src, uint8_t *dst,
630 uint32_t offset, uint32_t len)
633 uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
635 /* iterate bytewise to get data */
636 for (idx = 0; idx < cnt; idx++) {
637 ulp_bs_get_msb(src, offset, ULP_BLOB_BYTE, &dst[idx]);
638 offset += ULP_BLOB_BYTE;
639 len -= ULP_BLOB_BYTE;
642 /* Extract the last reminder data that is not 8 byte boundary */
644 ulp_bs_get_msb(src, offset, len, &dst[idx]);
648 * Extract data from the binary blob using given offset.
650 * blob [in] The blob that data is extracted from. The blob must
651 * be initialized prior to pulling data.
653 * data [in] A pointer to put the data.
654 * data_size [in] size of the data buffer in bytes.
655 *offset [in] - Offset in the blob to extract the data in bits format.
656 * len [in] The number of bits to be pulled from the blob.
658 * Output: zero on success, -1 on failure
661 ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size,
662 uint16_t offset, uint16_t len)
664 /* validate the arguments */
665 if (!blob || (offset + len) > blob->bitlen ||
666 ULP_BYTE_2_BITS(data_size) < len) {
667 BNXT_TF_DBG(ERR, "invalid argument\n");
668 return -1; /* failure */
671 if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
672 ulp_bs_pull_msb(blob->data, data, offset, len);
674 ulp_bs_pull_lsb(blob->data, data, data_size, offset, len);
679 * Get the data portion of the binary blob.
681 * blob [in] The blob's data to be retrieved. The blob must be
682 * initialized prior to pushing data.
684 * datalen [out] The number of bits to that are filled.
686 * returns a byte array of the blob data. Returns NULL on error.
689 ulp_blob_data_get(struct ulp_blob *blob,
692 /* validate the arguments */
694 BNXT_TF_DBG(ERR, "invalid argument\n");
695 return NULL; /* failure */
697 *datalen = blob->write_idx;
702 * Get the data length of the binary blob.
704 * blob [in] The blob's data len to be retrieved.
706 * returns length of the binary blob
709 ulp_blob_data_len_get(struct ulp_blob *blob)
711 /* validate the arguments */
713 BNXT_TF_DBG(ERR, "invalid argument\n");
714 return 0; /* failure */
716 return blob->write_idx;
720 * Set the encap swap start index of the binary blob.
722 * blob [in] The blob's data to be retrieved. The blob must be
723 * initialized prior to pushing data.
728 ulp_blob_encap_swap_idx_set(struct ulp_blob *blob)
730 /* validate the arguments */
732 BNXT_TF_DBG(ERR, "invalid argument\n");
733 return; /* failure */
735 blob->encap_swap_idx = blob->write_idx;
739 * Perform the encap buffer swap to 64 bit reversal.
741 * blob [in] The blob's data to be used for swap.
746 ulp_blob_perform_encap_swap(struct ulp_blob *blob)
748 uint32_t i, idx = 0, end_idx = 0, roundoff;
749 uint8_t temp_val_1, temp_val_2;
751 /* validate the arguments */
753 BNXT_TF_DBG(ERR, "invalid argument\n");
754 return; /* failure */
756 idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx);
757 end_idx = ULP_BITS_2_BYTE(blob->write_idx);
758 roundoff = ULP_BYTE_2_BITS(ULP_BITS_2_BYTE(end_idx));
759 if (roundoff > end_idx) {
760 blob->write_idx += ULP_BYTE_2_BITS(roundoff - end_idx);
763 while (idx <= end_idx) {
764 for (i = 0; i < 4; i = i + 2) {
765 temp_val_1 = blob->data[idx + i];
766 temp_val_2 = blob->data[idx + i + 1];
767 blob->data[idx + i] = blob->data[idx + 6 - i];
768 blob->data[idx + i + 1] = blob->data[idx + 7 - i];
769 blob->data[idx + 7 - i] = temp_val_2;
770 blob->data[idx + 6 - i] = temp_val_1;
777 * Perform the blob buffer reversal byte wise.
778 * This api makes the first byte the last and
781 * blob [in] The blob's data to be used for swap.
782 * chunk_size[in] the swap is done within the chunk in bytes
787 ulp_blob_perform_byte_reverse(struct ulp_blob *blob,
790 uint32_t idx = 0, jdx = 0, num = 0;
794 /* validate the arguments */
796 BNXT_TF_DBG(ERR, "invalid argument\n");
797 return; /* failure */
801 num = ULP_BITS_2_BYTE(blob->write_idx) / chunk_size;
802 for (idx = 0; idx < num; idx++) {
803 for (jdx = 0; jdx < chunk_size / 2; jdx++) {
805 buff[jdx] = buff[(chunk_size - 1) - jdx];
806 buff[(chunk_size - 1) - jdx] = xchar;
813 * Perform the blob buffer 64 bit word swap.
814 * This api makes the first 4 bytes the last in
815 * a given 64 bit value and vice-versa.
817 * blob [in] The blob's data to be used for swap.
822 ulp_blob_perform_64B_word_swap(struct ulp_blob *blob)
826 uint32_t word_size = ULP_64B_IN_BYTES / 2;
828 /* validate the arguments */
830 BNXT_TF_DBG(ERR, "invalid argument\n");
831 return; /* failure */
833 num = ULP_BITS_2_BYTE(blob->write_idx);
834 for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
835 for (j = 0; j < word_size; j++) {
836 xchar = blob->data[i + j];
837 blob->data[i + j] = blob->data[i + j + word_size];
838 blob->data[i + j + word_size] = xchar;
844 * Perform the blob buffer 64 bit byte swap.
845 * This api makes the first byte the last in
846 * a given 64 bit value and vice-versa.
848 * blob [in] The blob's data to be used for swap.
853 ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob)
857 uint32_t offset = ULP_64B_IN_BYTES - 1;
859 /* validate the arguments */
861 BNXT_TF_DBG(ERR, "invalid argument\n");
862 return; /* failure */
864 num = ULP_BITS_2_BYTE(blob->write_idx);
865 for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
866 for (j = 0; j < (ULP_64B_IN_BYTES / 2); j++) {
867 xchar = blob->data[i + j];
868 blob->data[i + j] = blob->data[i + offset - j];
869 blob->data[i + offset - j] = xchar;
875 ulp_blob_msb_block_merge(struct ulp_blob *dst, struct ulp_blob *src,
876 uint32_t block_size, uint32_t pad)
878 uint32_t i, k, write_bytes, remaining;
880 uint8_t *src_buf = ulp_blob_data_get(src, &num);
883 for (i = 0; i < num;) {
884 if (((dst->write_idx % block_size) + (num - i)) > block_size)
885 write_bytes = block_size -
886 (dst->write_idx % block_size);
888 write_bytes = num - i;
889 for (k = 0; k < ULP_BITS_2_BYTE_NR(write_bytes); k++) {
890 ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE,
892 dst->write_idx += ULP_BLOB_BYTE;
895 remaining = write_bytes % ULP_BLOB_BYTE;
897 bluff = (*src_buf) & ((uint8_t)-1 <<
898 (ULP_BLOB_BYTE - remaining));
899 ulp_bs_put_msb(dst->data, dst->write_idx,
900 ULP_BLOB_BYTE, bluff);
901 dst->write_idx += remaining;
903 if (write_bytes != (num - i)) {
904 /* add the padding */
905 ulp_blob_pad_push(dst, pad);
907 ulp_bs_put_msb(dst->data, dst->write_idx,
908 ULP_BLOB_BYTE - remaining,
910 dst->write_idx += ULP_BLOB_BYTE - remaining;
920 * Perform the blob buffer merge.
921 * This api makes the src blob merged to the dst blob.
922 * The block size and pad size help in padding the dst blob
924 * dst [in] The destination blob, the blob to be merged.
925 * src [in] The src blob.
926 * block_size [in] The size of the block after which padding gets applied.
927 * pad [in] The size of the pad to be applied.
929 * returns 0 on success.
932 ulp_blob_block_merge(struct ulp_blob *dst, struct ulp_blob *src,
933 uint32_t block_size, uint32_t pad)
935 if (dst->byte_order == BNXT_ULP_BYTE_ORDER_BE &&
936 src->byte_order == BNXT_ULP_BYTE_ORDER_BE)
937 return ulp_blob_msb_block_merge(dst, src, block_size, pad);
939 BNXT_TF_DBG(ERR, "block merge not implemented yet\n");
944 ulp_blob_append(struct ulp_blob *dst, struct ulp_blob *src,
945 uint16_t src_offset, uint16_t src_len)
947 uint32_t k, remaining;
950 uint8_t *src_buf = ulp_blob_data_get(src, &num);
952 if ((src_offset + src_len) > num)
955 /* Only supporting BE for now */
956 if (src->byte_order != BNXT_ULP_BYTE_ORDER_BE ||
957 dst->byte_order != BNXT_ULP_BYTE_ORDER_BE)
960 /* Handle if the source offset is not on a byte boundary */
961 remaining = src_offset % ULP_BLOB_BYTE;
963 bluff = src_buf[src_offset / ULP_BLOB_BYTE] & ((uint8_t)-1 >>
964 (ULP_BLOB_BYTE - remaining));
965 ulp_bs_put_msb(dst->data, dst->write_idx,
966 ULP_BLOB_BYTE, bluff);
967 dst->write_idx += remaining;
968 src_offset += remaining;
971 src_buf += ULP_BITS_2_BYTE_NR(src_offset);
973 /* Push the byte aligned pieces */
974 for (k = 0; k < ULP_BITS_2_BYTE_NR(src_len); k++) {
975 ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE,
977 dst->write_idx += ULP_BLOB_BYTE;
981 /* Handle the remaining if length is not a byte boundary */
982 remaining = src_len % ULP_BLOB_BYTE;
984 bluff = (*src_buf) & ((uint8_t)-1 <<
985 (ULP_BLOB_BYTE - remaining));
986 ulp_bs_put_msb(dst->data, dst->write_idx,
987 ULP_BLOB_BYTE, bluff);
988 dst->write_idx += remaining;
995 * Perform the blob buffer copy.
996 * This api makes the src blob merged to the dst blob.
998 * dst [in] The destination blob, the blob to be merged.
999 * src [in] The src blob.
1001 * returns 0 on success.
1004 ulp_blob_buffer_copy(struct ulp_blob *dst, struct ulp_blob *src)
1006 if ((dst->write_idx + src->write_idx) > dst->bitlen) {
1007 BNXT_TF_DBG(ERR, "source buffer too large\n");
1010 if (ULP_BITS_IS_BYTE_NOT_ALIGNED(dst->write_idx) ||
1011 ULP_BITS_IS_BYTE_NOT_ALIGNED(src->write_idx)) {
1012 BNXT_TF_DBG(ERR, "source buffer is not aligned\n");
1015 memcpy(&dst->data[ULP_BITS_2_BYTE_NR(dst->write_idx)],
1016 src->data, ULP_BITS_2_BYTE_NR(src->write_idx));
1017 dst->write_idx += src->write_idx;
1022 * Read data from the operand
1024 * operand [in] A pointer to a 16 Byte operand
1026 * val [in/out] The variable to copy the operand to
1028 * bytes [in] The number of bytes to read into val
1030 * returns number of bits read, zero on error
1033 ulp_operand_read(uint8_t *operand,
1037 /* validate the arguments */
1038 if (!operand || !val) {
1039 BNXT_TF_DBG(ERR, "invalid argument\n");
1040 return 0; /* failure */
1042 memcpy(val, operand, bytes);
1047 * Check the buffer is empty
1049 * buf [in] The buffer
1050 * size [in] The size of the buffer
1053 int32_t ulp_buffer_is_empty(const uint8_t *buf, uint32_t size)
1055 return buf[0] == 0 && !memcmp(buf, buf + 1, size - 1);
1058 /* Function to check if bitmap is zero.Return 1 on success */
1059 uint32_t ulp_bitmap_is_zero(uint8_t *bitmap, int32_t size)
1061 while (size-- > 0) {
1069 /* Function to check if bitmap is ones. Return 1 on success */
1070 uint32_t ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size)
1072 while (size-- > 0) {
1073 if (*bitmap != 0xFF)
1080 /* Function to check if bitmap is not zero. Return 1 on success */
1081 uint32_t ulp_bitmap_notzero(const uint8_t *bitmap, int32_t size)
1083 while (size-- > 0) {
1091 /* returns 0 if input is power of 2 */
1092 int32_t ulp_util_is_power_of_2(uint64_t x)