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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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