188badb3aSMike Baucom /* SPDX-License-Identifier: BSD-3-Clause 2e6e8f03eSRandy Schacher * Copyright(c) 2014-2023 Broadcom 388badb3aSMike Baucom * All rights reserved. 488badb3aSMike Baucom */ 588badb3aSMike Baucom 63fe124d2SKishore Padmanabha #include <rte_common.h> 788badb3aSMike Baucom #include "ulp_utils.h" 888badb3aSMike Baucom #include "bnxt_tf_common.h" 988badb3aSMike Baucom 1088badb3aSMike Baucom /* 1188badb3aSMike Baucom * Initialize the regfile structure for writing 1288badb3aSMike Baucom * 1388badb3aSMike Baucom * regfile [in] Ptr to a regfile instance 1488badb3aSMike Baucom * 15*c569279aSShuanglin Wang * returns zero on success 1688badb3aSMike Baucom */ 17*c569279aSShuanglin Wang int32_t 1888badb3aSMike Baucom ulp_regfile_init(struct ulp_regfile *regfile) 1988badb3aSMike Baucom { 2088badb3aSMike Baucom /* validate the arguments */ 2188badb3aSMike Baucom if (!regfile) { 22dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 23*c569279aSShuanglin Wang return -EINVAL; 2488badb3aSMike Baucom } 2588badb3aSMike Baucom memset(regfile, 0, sizeof(struct ulp_regfile)); 26*c569279aSShuanglin Wang return 0; /* Success */ 2788badb3aSMike Baucom } 2888badb3aSMike Baucom 2988badb3aSMike Baucom /* 3088badb3aSMike Baucom * Read a value from the regfile 3188badb3aSMike Baucom * 3288badb3aSMike Baucom * regfile [in] The regfile instance. Must be initialized prior to being used 3388badb3aSMike Baucom * 3488badb3aSMike Baucom * field [in] The field to be read within the regfile. 3588badb3aSMike Baucom * 3688badb3aSMike Baucom * data [in/out] 3788badb3aSMike Baucom * 38*c569279aSShuanglin Wang * returns zero on success 3988badb3aSMike Baucom */ 40*c569279aSShuanglin Wang int32_t 4188badb3aSMike Baucom ulp_regfile_read(struct ulp_regfile *regfile, 42a2417601SKishore Padmanabha enum bnxt_ulp_rf_idx field, 4388badb3aSMike Baucom uint64_t *data) 4488badb3aSMike Baucom { 4588badb3aSMike Baucom /* validate the arguments */ 46a2417601SKishore Padmanabha if (!regfile || field >= BNXT_ULP_RF_IDX_LAST) { 47dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 48*c569279aSShuanglin Wang return -EINVAL; 4988badb3aSMike Baucom } 5088badb3aSMike Baucom 5188badb3aSMike Baucom *data = regfile->entry[field].data; 52*c569279aSShuanglin Wang return 0; 5388badb3aSMike Baucom } 5488badb3aSMike Baucom 5588badb3aSMike Baucom /* 5688badb3aSMike Baucom * Write a value to the regfile 5788badb3aSMike Baucom * 5888badb3aSMike Baucom * regfile [in] The regfile instance. Must be initialized prior to being used 5988badb3aSMike Baucom * 6088badb3aSMike Baucom * field [in] The field to be written within the regfile. 6188badb3aSMike Baucom * 6288badb3aSMike Baucom * data [in] The value is written into this variable. It is going to be in the 6388badb3aSMike Baucom * same byte order as it was written. 6488badb3aSMike Baucom * 65f63aa27dSKishore Padmanabha * size [in] The size in bytes of the value being written into this 6688badb3aSMike Baucom * variable. 6788badb3aSMike Baucom * 68a2417601SKishore Padmanabha * returns 0 on success 6988badb3aSMike Baucom */ 70a2417601SKishore Padmanabha int32_t 7188badb3aSMike Baucom ulp_regfile_write(struct ulp_regfile *regfile, 72a2417601SKishore Padmanabha enum bnxt_ulp_rf_idx field, 7388badb3aSMike Baucom uint64_t data) 7488badb3aSMike Baucom { 7588badb3aSMike Baucom /* validate the arguments */ 76a2417601SKishore Padmanabha if (!regfile || field >= BNXT_ULP_RF_IDX_LAST) { 77dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 78a2417601SKishore Padmanabha return -EINVAL; /* failure */ 7988badb3aSMike Baucom } 8088badb3aSMike Baucom 8188badb3aSMike Baucom regfile->entry[field].data = data; 82a2417601SKishore Padmanabha return 0; /* Success */ 8388badb3aSMike Baucom } 8488badb3aSMike Baucom 8588badb3aSMike Baucom static void 8688badb3aSMike Baucom ulp_bs_put_msb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val) 8788badb3aSMike Baucom { 8888badb3aSMike Baucom uint8_t bitoffs = bitpos % 8; 8988badb3aSMike Baucom uint16_t index = bitpos / 8; 9088badb3aSMike Baucom uint8_t mask; 9188badb3aSMike Baucom uint8_t tmp; 9288badb3aSMike Baucom int8_t shift; 9388badb3aSMike Baucom 9488badb3aSMike Baucom tmp = bs[index]; 9588badb3aSMike Baucom mask = ((uint8_t)-1 >> (8 - bitlen)); 9688badb3aSMike Baucom shift = 8 - bitoffs - bitlen; 9788badb3aSMike Baucom val &= mask; 9888badb3aSMike Baucom 9988badb3aSMike Baucom if (shift >= 0) { 10088badb3aSMike Baucom tmp &= ~(mask << shift); 10188badb3aSMike Baucom tmp |= val << shift; 10288badb3aSMike Baucom bs[index] = tmp; 10388badb3aSMike Baucom } else { 10488badb3aSMike Baucom tmp &= ~((uint8_t)-1 >> bitoffs); 10588badb3aSMike Baucom tmp |= val >> -shift; 10688badb3aSMike Baucom bs[index++] = tmp; 10788badb3aSMike Baucom 10888badb3aSMike Baucom tmp = bs[index]; 10988badb3aSMike Baucom tmp &= ((uint8_t)-1 >> (bitlen - (8 - bitoffs))); 11088badb3aSMike Baucom tmp |= val << (8 + shift); 11188badb3aSMike Baucom bs[index] = tmp; 11288badb3aSMike Baucom } 11388badb3aSMike Baucom } 11488badb3aSMike Baucom 11588badb3aSMike Baucom static void 11688badb3aSMike Baucom ulp_bs_put_lsb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val) 11788badb3aSMike Baucom { 11888badb3aSMike Baucom uint8_t bitoffs = bitpos % 8; 11988badb3aSMike Baucom uint16_t index = bitpos / 8; 12088badb3aSMike Baucom uint8_t mask; 12188badb3aSMike Baucom uint8_t tmp; 12288badb3aSMike Baucom uint8_t shift; 12388badb3aSMike Baucom uint8_t partial; 12488badb3aSMike Baucom 12588badb3aSMike Baucom tmp = bs[index]; 12688badb3aSMike Baucom shift = bitoffs; 12788badb3aSMike Baucom 12888badb3aSMike Baucom if (bitoffs + bitlen <= 8) { 12988badb3aSMike Baucom mask = ((1 << bitlen) - 1) << shift; 13088badb3aSMike Baucom tmp &= ~mask; 13188badb3aSMike Baucom tmp |= ((val << shift) & mask); 13288badb3aSMike Baucom bs[index] = tmp; 13388badb3aSMike Baucom } else { 13488badb3aSMike Baucom partial = 8 - bitoffs; 13588badb3aSMike Baucom mask = ((1 << partial) - 1) << shift; 13688badb3aSMike Baucom tmp &= ~mask; 13788badb3aSMike Baucom tmp |= ((val << shift) & mask); 13888badb3aSMike Baucom bs[index++] = tmp; 13988badb3aSMike Baucom 14088badb3aSMike Baucom val >>= partial; 14188badb3aSMike Baucom partial = bitlen - partial; 14288badb3aSMike Baucom mask = ((1 << partial) - 1); 14388badb3aSMike Baucom tmp = bs[index]; 14488badb3aSMike Baucom tmp &= ~mask; 14588badb3aSMike Baucom tmp |= (val & mask); 14688badb3aSMike Baucom bs[index] = tmp; 14788badb3aSMike Baucom } 14888badb3aSMike Baucom } 14988badb3aSMike Baucom 150f634204bSKishore Padmanabha /* 151f634204bSKishore Padmanabha * Add data to the byte array in Little endian format. 152f634204bSKishore Padmanabha * 153f634204bSKishore Padmanabha * bs [in] The byte array where data is pushed 154f634204bSKishore Padmanabha * 155f634204bSKishore Padmanabha * pos [in] The offset where data is pushed 156f634204bSKishore Padmanabha * 157f634204bSKishore Padmanabha * len [in] The number of bits to be added to the data array. 158f634204bSKishore Padmanabha * 159f634204bSKishore Padmanabha * val [in] The data to be added to the data array. 160f634204bSKishore Padmanabha * 161f634204bSKishore Padmanabha * returns the number of bits pushed. 162f634204bSKishore Padmanabha */ 163f634204bSKishore Padmanabha uint32_t 16488badb3aSMike Baucom ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val) 16588badb3aSMike Baucom { 16688badb3aSMike Baucom int i; 16788badb3aSMike Baucom int cnt = (len) / 8; 16888badb3aSMike Baucom int tlen = len; 16988badb3aSMike Baucom 17088badb3aSMike Baucom if (cnt > 0 && !(len % 8)) 17188badb3aSMike Baucom cnt -= 1; 17288badb3aSMike Baucom 17388badb3aSMike Baucom for (i = 0; i < cnt; i++) { 17488badb3aSMike Baucom ulp_bs_put_lsb(bs, pos, 8, val[cnt - i]); 17588badb3aSMike Baucom pos += 8; 17688badb3aSMike Baucom tlen -= 8; 17788badb3aSMike Baucom } 17888badb3aSMike Baucom 17988badb3aSMike Baucom /* Handle the remainder bits */ 18088badb3aSMike Baucom if (tlen) 18188badb3aSMike Baucom ulp_bs_put_lsb(bs, pos, tlen, val[0]); 18288badb3aSMike Baucom return len; 18388badb3aSMike Baucom } 18488badb3aSMike Baucom 185f634204bSKishore Padmanabha /* 186f634204bSKishore Padmanabha * Add data to the byte array in Big endian format. 187f634204bSKishore Padmanabha * 188f634204bSKishore Padmanabha * bs [in] The byte array where data is pushed 189f634204bSKishore Padmanabha * 190f634204bSKishore Padmanabha * pos [in] The offset where data is pushed 191f634204bSKishore Padmanabha * 192f634204bSKishore Padmanabha * len [in] The number of bits to be added to the data array. 193f634204bSKishore Padmanabha * 194f634204bSKishore Padmanabha * val [in] The data to be added to the data array. 195f634204bSKishore Padmanabha * 196f634204bSKishore Padmanabha * returns the number of bits pushed. 197f634204bSKishore Padmanabha */ 198f634204bSKishore Padmanabha uint32_t 19988badb3aSMike Baucom ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val) 20088badb3aSMike Baucom { 20188badb3aSMike Baucom int i; 20288badb3aSMike Baucom int cnt = (len + 7) / 8; 20388badb3aSMike Baucom 20488badb3aSMike Baucom /* Handle any remainder bits */ 20588badb3aSMike Baucom int tmp = len % 8; 20688badb3aSMike Baucom 20788badb3aSMike Baucom if (!tmp) 20888badb3aSMike Baucom tmp = 8; 20988badb3aSMike Baucom 21088badb3aSMike Baucom ulp_bs_put_msb(bs, pos, tmp, val[0]); 21188badb3aSMike Baucom 21288badb3aSMike Baucom pos += tmp; 21388badb3aSMike Baucom 21488badb3aSMike Baucom for (i = 1; i < cnt; i++) { 21588badb3aSMike Baucom ulp_bs_put_msb(bs, pos, 8, val[i]); 21688badb3aSMike Baucom pos += 8; 21788badb3aSMike Baucom } 21888badb3aSMike Baucom 21988badb3aSMike Baucom return len; 22088badb3aSMike Baucom } 22188badb3aSMike Baucom 22288badb3aSMike Baucom /* 22388badb3aSMike Baucom * Initializes the blob structure for creating binary blob 22488badb3aSMike Baucom * 22588badb3aSMike Baucom * blob [in] The blob to be initialized 22688badb3aSMike Baucom * 22788badb3aSMike Baucom * bitlen [in] The bit length of the blob 22888badb3aSMike Baucom * 22988badb3aSMike Baucom * order [in] The byte order for the blob. Currently only supporting 23088badb3aSMike Baucom * big endian. All fields are packed with this order. 23188badb3aSMike Baucom * 232*c569279aSShuanglin Wang * returns zero on success 2333fe124d2SKishore Padmanabha * Notes - If bitlen is zero then set it to max. 23488badb3aSMike Baucom */ 235*c569279aSShuanglin Wang int32_t 23688badb3aSMike Baucom ulp_blob_init(struct ulp_blob *blob, 23788badb3aSMike Baucom uint16_t bitlen, 23888badb3aSMike Baucom enum bnxt_ulp_byte_order order) 23988badb3aSMike Baucom { 24088badb3aSMike Baucom /* validate the arguments */ 24188badb3aSMike Baucom if (!blob || bitlen > (8 * sizeof(blob->data))) { 242dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 243*c569279aSShuanglin Wang return -EINVAL; 24488badb3aSMike Baucom } 2453fe124d2SKishore Padmanabha if (bitlen) 24688badb3aSMike Baucom blob->bitlen = bitlen; 2473fe124d2SKishore Padmanabha else 2483fe124d2SKishore Padmanabha blob->bitlen = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 24988badb3aSMike Baucom blob->byte_order = order; 25088badb3aSMike Baucom blob->write_idx = 0; 25188badb3aSMike Baucom memset(blob->data, 0, sizeof(blob->data)); 252*c569279aSShuanglin Wang return 0; /* Success */ 25388badb3aSMike Baucom } 25488badb3aSMike Baucom 25588badb3aSMike Baucom /* 25688badb3aSMike Baucom * Add data to the binary blob at the current offset. 25788badb3aSMike Baucom * 25888badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 25988badb3aSMike Baucom * be initialized prior to pushing data. 26088badb3aSMike Baucom * 26188badb3aSMike Baucom * data [in] A pointer to bytes to be added to the blob. 26288badb3aSMike Baucom * 26388badb3aSMike Baucom * datalen [in] The number of bits to be added to the blob. 26488badb3aSMike Baucom * 26588badb3aSMike Baucom * The offset of the data is updated after each push of data. 266*c569279aSShuanglin Wang * 267*c569279aSShuanglin Wang * returns zero on success 26888badb3aSMike Baucom */ 26988badb3aSMike Baucom #define ULP_BLOB_BYTE 8 27088badb3aSMike Baucom #define ULP_BLOB_BYTE_HEX 0xFF 27188badb3aSMike Baucom #define BLOB_MASK_CAL(x) ((0xFF << (x)) & 0xFF) 272*c569279aSShuanglin Wang int32_t 27388badb3aSMike Baucom ulp_blob_push(struct ulp_blob *blob, 27488badb3aSMike Baucom uint8_t *data, 27588badb3aSMike Baucom uint32_t datalen) 27688badb3aSMike Baucom { 27788badb3aSMike Baucom uint32_t rc; 27888badb3aSMike Baucom 27988badb3aSMike Baucom /* validate the arguments */ 28088badb3aSMike Baucom if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx)) { 281dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 282*c569279aSShuanglin Wang return -EINVAL; 28388badb3aSMike Baucom } 28488badb3aSMike Baucom 28588badb3aSMike Baucom if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) 28688badb3aSMike Baucom rc = ulp_bs_push_msb(blob->data, 28788badb3aSMike Baucom blob->write_idx, 28888badb3aSMike Baucom datalen, 28988badb3aSMike Baucom data); 29088badb3aSMike Baucom else 29188badb3aSMike Baucom rc = ulp_bs_push_lsb(blob->data, 29288badb3aSMike Baucom blob->write_idx, 29388badb3aSMike Baucom datalen, 29488badb3aSMike Baucom data); 29588badb3aSMike Baucom if (!rc) { 296dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to write blob\n"); 297*c569279aSShuanglin Wang return -EINVAL; 29888badb3aSMike Baucom } 29988badb3aSMike Baucom blob->write_idx += datalen; 300*c569279aSShuanglin Wang return 0; 30188badb3aSMike Baucom } 30288badb3aSMike Baucom 30388badb3aSMike Baucom /* 3047e604e7fSKishore Padmanabha * Insert data into the binary blob at the given offset. 3057e604e7fSKishore Padmanabha * 3067e604e7fSKishore Padmanabha * blob [in] The blob that data is added to. The blob must 3077e604e7fSKishore Padmanabha * be initialized prior to pushing data. 3087e604e7fSKishore Padmanabha * 3097e604e7fSKishore Padmanabha * offset [in] The offset where the data needs to be inserted. 3107e604e7fSKishore Padmanabha * 3117e604e7fSKishore Padmanabha * data [in/out] A pointer to bytes to be added to the blob. 3127e604e7fSKishore Padmanabha * 3137e604e7fSKishore Padmanabha * datalen [in] The number of bits to be added to the blob. 3147e604e7fSKishore Padmanabha * 3157e604e7fSKishore Padmanabha * The offset of the data is updated after each push of data. 316*c569279aSShuanglin Wang * 317*c569279aSShuanglin Wang * returns zero on success 3187e604e7fSKishore Padmanabha */ 319*c569279aSShuanglin Wang int32_t 3207e604e7fSKishore Padmanabha ulp_blob_insert(struct ulp_blob *blob, uint32_t offset, 3217e604e7fSKishore Padmanabha uint8_t *data, uint32_t datalen) 3227e604e7fSKishore Padmanabha { 3237e604e7fSKishore Padmanabha uint32_t rc; 3247e604e7fSKishore Padmanabha uint8_t local_data[BNXT_ULP_FLMP_BLOB_SIZE]; 3257e604e7fSKishore Padmanabha uint16_t mov_len; 3267e604e7fSKishore Padmanabha 3277e604e7fSKishore Padmanabha /* validate the arguments */ 3287e604e7fSKishore Padmanabha if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx) || 3297e604e7fSKishore Padmanabha offset > blob->write_idx) { 330dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 331*c569279aSShuanglin Wang return -EINVAL; 3327e604e7fSKishore Padmanabha } 3337e604e7fSKishore Padmanabha 3347e604e7fSKishore Padmanabha mov_len = blob->write_idx - offset; 3357e604e7fSKishore Padmanabha /* If offset and data len are not 8 bit aligned then return error */ 3367e604e7fSKishore Padmanabha if (ULP_BITS_IS_BYTE_NOT_ALIGNED(offset) || 3377e604e7fSKishore Padmanabha ULP_BITS_IS_BYTE_NOT_ALIGNED(datalen)) { 338dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument, not aligned\n"); 339*c569279aSShuanglin Wang return -EINVAL; 3407e604e7fSKishore Padmanabha } 3417e604e7fSKishore Padmanabha 3427e604e7fSKishore Padmanabha /* copy the data so we can move the data */ 3437e604e7fSKishore Padmanabha memcpy(local_data, &blob->data[ULP_BITS_2_BYTE_NR(offset)], 3447e604e7fSKishore Padmanabha ULP_BITS_2_BYTE(mov_len)); 3457e604e7fSKishore Padmanabha blob->write_idx = offset; 3467e604e7fSKishore Padmanabha if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) 3477e604e7fSKishore Padmanabha rc = ulp_bs_push_msb(blob->data, 3487e604e7fSKishore Padmanabha blob->write_idx, 3497e604e7fSKishore Padmanabha datalen, 3507e604e7fSKishore Padmanabha data); 3517e604e7fSKishore Padmanabha else 3527e604e7fSKishore Padmanabha rc = ulp_bs_push_lsb(blob->data, 3537e604e7fSKishore Padmanabha blob->write_idx, 3547e604e7fSKishore Padmanabha datalen, 3557e604e7fSKishore Padmanabha data); 3567e604e7fSKishore Padmanabha if (!rc) { 357dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to write blob\n"); 358*c569279aSShuanglin Wang return -EINVAL; 3597e604e7fSKishore Padmanabha } 3607e604e7fSKishore Padmanabha /* copy the previously stored data */ 3617e604e7fSKishore Padmanabha memcpy(&blob->data[ULP_BITS_2_BYTE_NR(offset + datalen)], local_data, 3627e604e7fSKishore Padmanabha ULP_BITS_2_BYTE(mov_len)); 3637e604e7fSKishore Padmanabha blob->write_idx += (mov_len + datalen); 364*c569279aSShuanglin Wang return 0; 3657e604e7fSKishore Padmanabha } 3667e604e7fSKishore Padmanabha 3677e604e7fSKishore Padmanabha /* 36888badb3aSMike Baucom * Add data to the binary blob at the current offset. 36988badb3aSMike Baucom * 37088badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 37188badb3aSMike Baucom * be initialized prior to pushing data. 37288badb3aSMike Baucom * 37388badb3aSMike Baucom * data [in] 64-bit value to be added to the blob. 37488badb3aSMike Baucom * 37588badb3aSMike Baucom * datalen [in] The number of bits to be added to the blob. 37688badb3aSMike Baucom * 37788badb3aSMike Baucom * The offset of the data is updated after each push of data. 37888badb3aSMike Baucom * NULL returned on error, pointer pushed value otherwise. 37988badb3aSMike Baucom */ 38088badb3aSMike Baucom uint8_t * 38188badb3aSMike Baucom ulp_blob_push_64(struct ulp_blob *blob, 38288badb3aSMike Baucom uint64_t *data, 38388badb3aSMike Baucom uint32_t datalen) 38488badb3aSMike Baucom { 38588badb3aSMike Baucom uint8_t *val = (uint8_t *)data; 38688badb3aSMike Baucom int rc; 38788badb3aSMike Baucom 38888badb3aSMike Baucom int size = (datalen + 7) / 8; 38988badb3aSMike Baucom 39088badb3aSMike Baucom if (!blob || !data || 39188badb3aSMike Baucom datalen > (uint32_t)(blob->bitlen - blob->write_idx)) { 392dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 393*c569279aSShuanglin Wang return NULL; 39488badb3aSMike Baucom } 39588badb3aSMike Baucom 39688badb3aSMike Baucom rc = ulp_blob_push(blob, &val[8 - size], datalen); 397*c569279aSShuanglin Wang if (rc) 398*c569279aSShuanglin Wang return NULL; 39988badb3aSMike Baucom 40088badb3aSMike Baucom return &val[8 - size]; 40188badb3aSMike Baucom } 40288badb3aSMike Baucom 40388badb3aSMike Baucom /* 404a2be13e1SKishore Padmanabha * Add data to the binary blob at the current offset. 405a2be13e1SKishore Padmanabha * 406a2be13e1SKishore Padmanabha * blob [in] The blob that data is added to. The blob must 407a2be13e1SKishore Padmanabha * be initialized prior to pushing data. 408a2be13e1SKishore Padmanabha * 409a2be13e1SKishore Padmanabha * data [in] 32-bit value to be added to the blob. 410a2be13e1SKishore Padmanabha * 411f63aa27dSKishore Padmanabha * datalen [in] The number of bits to be added to the blob. 412a2be13e1SKishore Padmanabha * 413a2be13e1SKishore Padmanabha * The offset of the data is updated after each push of data. 414a2be13e1SKishore Padmanabha * NULL returned on error, pointer pushed value otherwise. 415a2be13e1SKishore Padmanabha */ 416a2be13e1SKishore Padmanabha uint8_t * 417a2be13e1SKishore Padmanabha ulp_blob_push_32(struct ulp_blob *blob, 418a2be13e1SKishore Padmanabha uint32_t *data, 419a2be13e1SKishore Padmanabha uint32_t datalen) 420a2be13e1SKishore Padmanabha { 421a2be13e1SKishore Padmanabha uint8_t *val = (uint8_t *)data; 422a2be13e1SKishore Padmanabha uint32_t rc; 423a2be13e1SKishore Padmanabha uint32_t size = ULP_BITS_2_BYTE(datalen); 424a2be13e1SKishore Padmanabha 425a2be13e1SKishore Padmanabha if (!data || size > sizeof(uint32_t)) { 426dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 427*c569279aSShuanglin Wang return NULL; 428a2be13e1SKishore Padmanabha } 429a2be13e1SKishore Padmanabha 430a2be13e1SKishore Padmanabha rc = ulp_blob_push(blob, &val[sizeof(uint32_t) - size], datalen); 431*c569279aSShuanglin Wang if (rc) 432*c569279aSShuanglin Wang return NULL; 433a2be13e1SKishore Padmanabha 434a2be13e1SKishore Padmanabha return &val[sizeof(uint32_t) - size]; 435a2be13e1SKishore Padmanabha } 436a2be13e1SKishore Padmanabha 437a2be13e1SKishore Padmanabha /* 43888badb3aSMike Baucom * Add encap data to the binary blob at the current offset. 43988badb3aSMike Baucom * 44088badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 44188badb3aSMike Baucom * be initialized prior to pushing data. 44288badb3aSMike Baucom * 44388badb3aSMike Baucom * data [in] value to be added to the blob. 44488badb3aSMike Baucom * 44588badb3aSMike Baucom * datalen [in] The number of bits to be added to the blob. 44688badb3aSMike Baucom * 44788badb3aSMike Baucom * The offset of the data is updated after each push of data. 44888badb3aSMike Baucom * NULL returned on error, pointer pushed value otherwise. 44988badb3aSMike Baucom */ 450286569d5SKishore Padmanabha int32_t 45188badb3aSMike Baucom ulp_blob_push_encap(struct ulp_blob *blob, 45288badb3aSMike Baucom uint8_t *data, 45388badb3aSMike Baucom uint32_t datalen) 45488badb3aSMike Baucom { 45588badb3aSMike Baucom uint8_t *val = (uint8_t *)data; 45688badb3aSMike Baucom uint32_t initial_size, write_size = datalen; 45788badb3aSMike Baucom uint32_t size = 0; 45888badb3aSMike Baucom 45988badb3aSMike Baucom if (!blob || !data || 46088badb3aSMike Baucom datalen > (uint32_t)(blob->bitlen - blob->write_idx)) { 461dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 462286569d5SKishore Padmanabha return -1; 46388badb3aSMike Baucom } 46488badb3aSMike Baucom 46588badb3aSMike Baucom initial_size = ULP_BYTE_2_BITS(sizeof(uint64_t)) - 46688badb3aSMike Baucom (blob->write_idx % ULP_BYTE_2_BITS(sizeof(uint64_t))); 46788badb3aSMike Baucom while (write_size > 0) { 46888badb3aSMike Baucom if (initial_size && write_size > initial_size) { 46988badb3aSMike Baucom size = initial_size; 47088badb3aSMike Baucom initial_size = 0; 47188badb3aSMike Baucom } else if (initial_size && write_size <= initial_size) { 47288badb3aSMike Baucom size = write_size; 47388badb3aSMike Baucom initial_size = 0; 47488badb3aSMike Baucom } else if (write_size > ULP_BYTE_2_BITS(sizeof(uint64_t))) { 47588badb3aSMike Baucom size = ULP_BYTE_2_BITS(sizeof(uint64_t)); 47688badb3aSMike Baucom } else { 47788badb3aSMike Baucom size = write_size; 47888badb3aSMike Baucom } 479*c569279aSShuanglin Wang if (ulp_blob_push(blob, val, size)) { 480dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "push field failed\n"); 481286569d5SKishore Padmanabha return -1; 48288badb3aSMike Baucom } 48388badb3aSMike Baucom val += ULP_BITS_2_BYTE(size); 48488badb3aSMike Baucom write_size -= size; 48588badb3aSMike Baucom } 48688badb3aSMike Baucom return datalen; 48788badb3aSMike Baucom } 48888badb3aSMike Baucom 48988badb3aSMike Baucom /* 49088badb3aSMike Baucom * Adds pad to an initialized blob at the current offset 49188badb3aSMike Baucom * 49288badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 49388badb3aSMike Baucom * be initialized prior to pushing data. 49488badb3aSMike Baucom * 49588badb3aSMike Baucom * datalen [in] The number of bits of pad to add 49688badb3aSMike Baucom * 497a4651725SMike Baucom * returns the number of pad bits added, -1 on failure 49888badb3aSMike Baucom */ 499a4651725SMike Baucom int32_t 50088badb3aSMike Baucom ulp_blob_pad_push(struct ulp_blob *blob, 50188badb3aSMike Baucom uint32_t datalen) 50288badb3aSMike Baucom { 50388badb3aSMike Baucom if (datalen > (uint32_t)(blob->bitlen - blob->write_idx)) { 504dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Pad too large for blob\n"); 505f634204bSKishore Padmanabha return -1; 50688badb3aSMike Baucom } 50788badb3aSMike Baucom 50888badb3aSMike Baucom blob->write_idx += datalen; 50988badb3aSMike Baucom return datalen; 51088badb3aSMike Baucom } 51188badb3aSMike Baucom 5123fe124d2SKishore Padmanabha /* 5133fe124d2SKishore Padmanabha * Adds pad to an initialized blob at the current offset based on 5143fe124d2SKishore Padmanabha * the alignment. 5153fe124d2SKishore Padmanabha * 5163fe124d2SKishore Padmanabha * blob [in] The blob that needs to be aligned 5173fe124d2SKishore Padmanabha * 5183fe124d2SKishore Padmanabha * align [in] Alignment in bits. 5193fe124d2SKishore Padmanabha * 5203fe124d2SKishore Padmanabha * returns the number of pad bits added, -1 on failure 5213fe124d2SKishore Padmanabha */ 5223fe124d2SKishore Padmanabha int32_t 5233fe124d2SKishore Padmanabha ulp_blob_pad_align(struct ulp_blob *blob, 5243fe124d2SKishore Padmanabha uint32_t align) 5253fe124d2SKishore Padmanabha { 5263fe124d2SKishore Padmanabha int32_t pad = 0; 5273fe124d2SKishore Padmanabha 5283fe124d2SKishore Padmanabha pad = RTE_ALIGN(blob->write_idx, align) - blob->write_idx; 5293fe124d2SKishore Padmanabha if (pad > (int32_t)(blob->bitlen - blob->write_idx)) { 530dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Pad too large for blob\n"); 5313fe124d2SKishore Padmanabha return -1; 5323fe124d2SKishore Padmanabha } 5333fe124d2SKishore Padmanabha blob->write_idx += pad; 5343fe124d2SKishore Padmanabha return pad; 5353fe124d2SKishore Padmanabha } 5363fe124d2SKishore Padmanabha 537afd35335SKishore Padmanabha /* Get data from src and put into dst using little-endian format */ 538afd35335SKishore Padmanabha static void 539afd35335SKishore Padmanabha ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst) 540afd35335SKishore Padmanabha { 541afd35335SKishore Padmanabha uint8_t bitoffs = bitpos % ULP_BLOB_BYTE; 542afd35335SKishore Padmanabha uint16_t index = ULP_BITS_2_BYTE_NR(bitpos); 543afd35335SKishore Padmanabha uint8_t mask, partial, shift; 544afd35335SKishore Padmanabha 545afd35335SKishore Padmanabha shift = bitoffs; 546afd35335SKishore Padmanabha partial = ULP_BLOB_BYTE - bitoffs; 547afd35335SKishore Padmanabha if (bitoffs + bitlen <= ULP_BLOB_BYTE) { 548afd35335SKishore Padmanabha mask = ((1 << bitlen) - 1) << shift; 549afd35335SKishore Padmanabha *dst = (src[index] & mask) >> shift; 550afd35335SKishore Padmanabha } else { 551afd35335SKishore Padmanabha mask = ((1 << partial) - 1) << shift; 552afd35335SKishore Padmanabha *dst = (src[index] & mask) >> shift; 553afd35335SKishore Padmanabha index++; 554afd35335SKishore Padmanabha partial = bitlen - partial; 555afd35335SKishore Padmanabha mask = ((1 << partial) - 1); 556afd35335SKishore Padmanabha *dst |= (src[index] & mask) << (ULP_BLOB_BYTE - bitoffs); 557afd35335SKishore Padmanabha } 558afd35335SKishore Padmanabha } 559afd35335SKishore Padmanabha 560f634204bSKishore Padmanabha /* 561f634204bSKishore Padmanabha * Get data from the byte array in Little endian format. 562f634204bSKishore Padmanabha * 563f634204bSKishore Padmanabha * src [in] The byte array where data is extracted from 564f634204bSKishore Padmanabha * 565f634204bSKishore Padmanabha * dst [out] The byte array where data is pulled into 566f634204bSKishore Padmanabha * 567f634204bSKishore Padmanabha * size [in] The size of dst array in bytes 568f634204bSKishore Padmanabha * 569f634204bSKishore Padmanabha * offset [in] The offset where data is pulled 570f634204bSKishore Padmanabha * 571f634204bSKishore Padmanabha * len [in] The number of bits to be extracted from the data array 572f634204bSKishore Padmanabha * 573f634204bSKishore Padmanabha * returns None. 574f634204bSKishore Padmanabha */ 575f634204bSKishore Padmanabha void 576afd35335SKishore Padmanabha ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size, 577afd35335SKishore Padmanabha uint32_t offset, uint32_t len) 578afd35335SKishore Padmanabha { 579afd35335SKishore Padmanabha uint32_t idx; 580afd35335SKishore Padmanabha uint32_t cnt = ULP_BITS_2_BYTE_NR(len); 581afd35335SKishore Padmanabha 582afd35335SKishore Padmanabha /* iterate bytewise to get data */ 583afd35335SKishore Padmanabha for (idx = 0; idx < cnt; idx++) { 584afd35335SKishore Padmanabha ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE, 585afd35335SKishore Padmanabha &dst[size - 1 - idx]); 586afd35335SKishore Padmanabha offset += ULP_BLOB_BYTE; 587afd35335SKishore Padmanabha len -= ULP_BLOB_BYTE; 588afd35335SKishore Padmanabha } 589afd35335SKishore Padmanabha 590afd35335SKishore Padmanabha /* Extract the last reminder data that is not 8 byte boundary */ 591afd35335SKishore Padmanabha if (len) 592afd35335SKishore Padmanabha ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]); 593afd35335SKishore Padmanabha } 594afd35335SKishore Padmanabha 595f634204bSKishore Padmanabha /* Get data from src and put into dst using big-endian format */ 596f634204bSKishore Padmanabha static void 597f634204bSKishore Padmanabha ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst) 598f634204bSKishore Padmanabha { 599f634204bSKishore Padmanabha uint8_t bitoffs = bitpos % ULP_BLOB_BYTE; 600f634204bSKishore Padmanabha uint16_t index = ULP_BITS_2_BYTE_NR(bitpos); 601f634204bSKishore Padmanabha uint8_t mask; 602f634204bSKishore Padmanabha int32_t shift; 603f634204bSKishore Padmanabha 604f634204bSKishore Padmanabha shift = ULP_BLOB_BYTE - bitoffs - bitlen; 605f634204bSKishore Padmanabha if (shift >= 0) { 606f634204bSKishore Padmanabha mask = 0xFF >> -bitlen; 607f634204bSKishore Padmanabha *dst = (src[index] >> shift) & mask; 608f634204bSKishore Padmanabha } else { 609f634204bSKishore Padmanabha *dst = (src[index] & (0xFF >> bitoffs)) << -shift; 610f634204bSKishore Padmanabha *dst |= src[index + 1] >> -shift; 611f634204bSKishore Padmanabha } 612f634204bSKishore Padmanabha } 613f634204bSKishore Padmanabha 614f634204bSKishore Padmanabha /* 615f634204bSKishore Padmanabha * Get data from the byte array in Big endian format. 616f634204bSKishore Padmanabha * 617f634204bSKishore Padmanabha * src [in] The byte array where data is extracted from 618f634204bSKishore Padmanabha * 619f634204bSKishore Padmanabha * dst [out] The byte array where data is pulled into 620f634204bSKishore Padmanabha * 621f634204bSKishore Padmanabha * offset [in] The offset where data is pulled 622f634204bSKishore Padmanabha * 623f634204bSKishore Padmanabha * len [in] The number of bits to be extracted from the data array 624f634204bSKishore Padmanabha * 625f634204bSKishore Padmanabha * returns None. 626f634204bSKishore Padmanabha */ 627f634204bSKishore Padmanabha void 628f634204bSKishore Padmanabha ulp_bs_pull_msb(uint8_t *src, uint8_t *dst, 629f634204bSKishore Padmanabha uint32_t offset, uint32_t len) 630f634204bSKishore Padmanabha { 631f634204bSKishore Padmanabha uint32_t idx; 632f634204bSKishore Padmanabha uint32_t cnt = ULP_BITS_2_BYTE_NR(len); 633f634204bSKishore Padmanabha 634f634204bSKishore Padmanabha /* iterate bytewise to get data */ 635f634204bSKishore Padmanabha for (idx = 0; idx < cnt; idx++) { 636f634204bSKishore Padmanabha ulp_bs_get_msb(src, offset, ULP_BLOB_BYTE, &dst[idx]); 637f634204bSKishore Padmanabha offset += ULP_BLOB_BYTE; 638f634204bSKishore Padmanabha len -= ULP_BLOB_BYTE; 639f634204bSKishore Padmanabha } 640f634204bSKishore Padmanabha 641f634204bSKishore Padmanabha /* Extract the last reminder data that is not 8 byte boundary */ 642f634204bSKishore Padmanabha if (len) 643f634204bSKishore Padmanabha ulp_bs_get_msb(src, offset, len, &dst[idx]); 644f634204bSKishore Padmanabha } 645f634204bSKishore Padmanabha 646afd35335SKishore Padmanabha /* 647afd35335SKishore Padmanabha * Extract data from the binary blob using given offset. 648afd35335SKishore Padmanabha * 649afd35335SKishore Padmanabha * blob [in] The blob that data is extracted from. The blob must 650afd35335SKishore Padmanabha * be initialized prior to pulling data. 651afd35335SKishore Padmanabha * 652afd35335SKishore Padmanabha * data [in] A pointer to put the data. 653afd35335SKishore Padmanabha * data_size [in] size of the data buffer in bytes. 654afd35335SKishore Padmanabha *offset [in] - Offset in the blob to extract the data in bits format. 655afd35335SKishore Padmanabha * len [in] The number of bits to be pulled from the blob. 656afd35335SKishore Padmanabha * 657afd35335SKishore Padmanabha * Output: zero on success, -1 on failure 658afd35335SKishore Padmanabha */ 659afd35335SKishore Padmanabha int32_t 660afd35335SKishore Padmanabha ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size, 661afd35335SKishore Padmanabha uint16_t offset, uint16_t len) 662afd35335SKishore Padmanabha { 663afd35335SKishore Padmanabha /* validate the arguments */ 664afd35335SKishore Padmanabha if (!blob || (offset + len) > blob->bitlen || 665afd35335SKishore Padmanabha ULP_BYTE_2_BITS(data_size) < len) { 666dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 667afd35335SKishore Padmanabha return -1; /* failure */ 668afd35335SKishore Padmanabha } 669afd35335SKishore Padmanabha 670f634204bSKishore Padmanabha if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) 671f634204bSKishore Padmanabha ulp_bs_pull_msb(blob->data, data, offset, len); 672f634204bSKishore Padmanabha else 673afd35335SKishore Padmanabha ulp_bs_pull_lsb(blob->data, data, data_size, offset, len); 674afd35335SKishore Padmanabha return 0; 675afd35335SKishore Padmanabha } 676afd35335SKishore Padmanabha 67788badb3aSMike Baucom /* 67888badb3aSMike Baucom * Get the data portion of the binary blob. 67988badb3aSMike Baucom * 68088badb3aSMike Baucom * blob [in] The blob's data to be retrieved. The blob must be 68188badb3aSMike Baucom * initialized prior to pushing data. 68288badb3aSMike Baucom * 683dd0191d5SShuanglin Wang * datalen [out] The number of bits that are filled. 68488badb3aSMike Baucom * 685dd0191d5SShuanglin Wang * Returns a byte array of the blob data or NULL on error. 68688badb3aSMike Baucom */ 68788badb3aSMike Baucom uint8_t * 68888badb3aSMike Baucom ulp_blob_data_get(struct ulp_blob *blob, 68988badb3aSMike Baucom uint16_t *datalen) 69088badb3aSMike Baucom { 69188badb3aSMike Baucom /* validate the arguments */ 69288badb3aSMike Baucom if (!blob) { 693dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 69488badb3aSMike Baucom return NULL; /* failure */ 69588badb3aSMike Baucom } 69688badb3aSMike Baucom *datalen = blob->write_idx; 69788badb3aSMike Baucom return blob->data; 69888badb3aSMike Baucom } 69988badb3aSMike Baucom 70088badb3aSMike Baucom /* 7013fe124d2SKishore Padmanabha * Get the data length of the binary blob. 7023fe124d2SKishore Padmanabha * 7033fe124d2SKishore Padmanabha * blob [in] The blob's data len to be retrieved. 7043fe124d2SKishore Padmanabha * 7053fe124d2SKishore Padmanabha * returns length of the binary blob 7063fe124d2SKishore Padmanabha */ 7073fe124d2SKishore Padmanabha uint16_t 7083fe124d2SKishore Padmanabha ulp_blob_data_len_get(struct ulp_blob *blob) 7093fe124d2SKishore Padmanabha { 7103fe124d2SKishore Padmanabha /* validate the arguments */ 7113fe124d2SKishore Padmanabha if (!blob) { 712dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 7133fe124d2SKishore Padmanabha return 0; /* failure */ 7143fe124d2SKishore Padmanabha } 7153fe124d2SKishore Padmanabha return blob->write_idx; 7163fe124d2SKishore Padmanabha } 7173fe124d2SKishore Padmanabha 7183fe124d2SKishore Padmanabha /* 71988badb3aSMike Baucom * Set the encap swap start index of the binary blob. 72088badb3aSMike Baucom * 72188badb3aSMike Baucom * blob [in] The blob's data to be retrieved. The blob must be 72288badb3aSMike Baucom * initialized prior to pushing data. 72388badb3aSMike Baucom * 72488badb3aSMike Baucom * returns void. 72588badb3aSMike Baucom */ 72688badb3aSMike Baucom void 72788badb3aSMike Baucom ulp_blob_encap_swap_idx_set(struct ulp_blob *blob) 72888badb3aSMike Baucom { 72988badb3aSMike Baucom /* validate the arguments */ 73088badb3aSMike Baucom if (!blob) { 731dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 73288badb3aSMike Baucom return; /* failure */ 73388badb3aSMike Baucom } 73488badb3aSMike Baucom blob->encap_swap_idx = blob->write_idx; 73588badb3aSMike Baucom } 73688badb3aSMike Baucom 73788badb3aSMike Baucom /* 73888badb3aSMike Baucom * Perform the encap buffer swap to 64 bit reversal. 73988badb3aSMike Baucom * 74088badb3aSMike Baucom * blob [in] The blob's data to be used for swap. 74188badb3aSMike Baucom * 74288badb3aSMike Baucom * returns void. 74388badb3aSMike Baucom */ 74488badb3aSMike Baucom void 74588badb3aSMike Baucom ulp_blob_perform_encap_swap(struct ulp_blob *blob) 74688badb3aSMike Baucom { 7479238ac2aSKishore Padmanabha uint32_t i, idx = 0, end_idx = 0, roundoff; 74888badb3aSMike Baucom uint8_t temp_val_1, temp_val_2; 74988badb3aSMike Baucom 75088badb3aSMike Baucom /* validate the arguments */ 75188badb3aSMike Baucom if (!blob) { 752dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 75388badb3aSMike Baucom return; /* failure */ 75488badb3aSMike Baucom } 755f0ca77fdSMike Baucom idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx); 75688badb3aSMike Baucom end_idx = ULP_BITS_2_BYTE(blob->write_idx); 7579238ac2aSKishore Padmanabha roundoff = ULP_BYTE_2_BITS(ULP_BITS_2_BYTE(end_idx)); 7589238ac2aSKishore Padmanabha if (roundoff > end_idx) { 7599238ac2aSKishore Padmanabha blob->write_idx += ULP_BYTE_2_BITS(roundoff - end_idx); 7609238ac2aSKishore Padmanabha end_idx = roundoff; 7619238ac2aSKishore Padmanabha } 76288badb3aSMike Baucom while (idx <= end_idx) { 76388badb3aSMike Baucom for (i = 0; i < 4; i = i + 2) { 76488badb3aSMike Baucom temp_val_1 = blob->data[idx + i]; 76588badb3aSMike Baucom temp_val_2 = blob->data[idx + i + 1]; 76688badb3aSMike Baucom blob->data[idx + i] = blob->data[idx + 6 - i]; 76788badb3aSMike Baucom blob->data[idx + i + 1] = blob->data[idx + 7 - i]; 76888badb3aSMike Baucom blob->data[idx + 7 - i] = temp_val_2; 76988badb3aSMike Baucom blob->data[idx + 6 - i] = temp_val_1; 77088badb3aSMike Baucom } 77188badb3aSMike Baucom idx += 8; 77288badb3aSMike Baucom } 77388badb3aSMike Baucom } 77488badb3aSMike Baucom 77588badb3aSMike Baucom /* 776a4651725SMike Baucom * Perform the blob buffer reversal byte wise. 777a4651725SMike Baucom * This api makes the first byte the last and 778a4651725SMike Baucom * vice-versa. 779a4651725SMike Baucom * 780a4651725SMike Baucom * blob [in] The blob's data to be used for swap. 7813fe124d2SKishore Padmanabha * chunk_size[in] the swap is done within the chunk in bytes 782a4651725SMike Baucom * 783a4651725SMike Baucom * returns void. 784a4651725SMike Baucom */ 785a4651725SMike Baucom void 7863fe124d2SKishore Padmanabha ulp_blob_perform_byte_reverse(struct ulp_blob *blob, 7873fe124d2SKishore Padmanabha uint32_t chunk_size) 788a4651725SMike Baucom { 7893fe124d2SKishore Padmanabha uint32_t idx = 0, jdx = 0, num = 0; 790a4651725SMike Baucom uint8_t xchar; 7913fe124d2SKishore Padmanabha uint8_t *buff; 792a4651725SMike Baucom 793a4651725SMike Baucom /* validate the arguments */ 794a4651725SMike Baucom if (!blob) { 795dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 796a4651725SMike Baucom return; /* failure */ 797a4651725SMike Baucom } 798a4651725SMike Baucom 7993fe124d2SKishore Padmanabha buff = blob->data; 8003fe124d2SKishore Padmanabha num = ULP_BITS_2_BYTE(blob->write_idx) / chunk_size; 8013fe124d2SKishore Padmanabha for (idx = 0; idx < num; idx++) { 8023fe124d2SKishore Padmanabha for (jdx = 0; jdx < chunk_size / 2; jdx++) { 8033fe124d2SKishore Padmanabha xchar = buff[jdx]; 8043fe124d2SKishore Padmanabha buff[jdx] = buff[(chunk_size - 1) - jdx]; 8053fe124d2SKishore Padmanabha buff[(chunk_size - 1) - jdx] = xchar; 8063fe124d2SKishore Padmanabha } 8073fe124d2SKishore Padmanabha buff += chunk_size; 808a4651725SMike Baucom } 809a4651725SMike Baucom } 810a4651725SMike Baucom 811a4651725SMike Baucom /* 8127e604e7fSKishore Padmanabha * Perform the blob buffer 64 bit word swap. 8137e604e7fSKishore Padmanabha * This api makes the first 4 bytes the last in 8147e604e7fSKishore Padmanabha * a given 64 bit value and vice-versa. 8157e604e7fSKishore Padmanabha * 8167e604e7fSKishore Padmanabha * blob [in] The blob's data to be used for swap. 8177e604e7fSKishore Padmanabha * 8187e604e7fSKishore Padmanabha * returns void. 8197e604e7fSKishore Padmanabha */ 8207e604e7fSKishore Padmanabha void 8217e604e7fSKishore Padmanabha ulp_blob_perform_64B_word_swap(struct ulp_blob *blob) 8227e604e7fSKishore Padmanabha { 8237e604e7fSKishore Padmanabha uint32_t i, j, num; 8247e604e7fSKishore Padmanabha uint8_t xchar; 8257e604e7fSKishore Padmanabha uint32_t word_size = ULP_64B_IN_BYTES / 2; 8267e604e7fSKishore Padmanabha 8277e604e7fSKishore Padmanabha /* validate the arguments */ 8287e604e7fSKishore Padmanabha if (!blob) { 829dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 8307e604e7fSKishore Padmanabha return; /* failure */ 8317e604e7fSKishore Padmanabha } 8327e604e7fSKishore Padmanabha num = ULP_BITS_2_BYTE(blob->write_idx); 8337e604e7fSKishore Padmanabha for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) { 8347e604e7fSKishore Padmanabha for (j = 0; j < word_size; j++) { 8357e604e7fSKishore Padmanabha xchar = blob->data[i + j]; 8367e604e7fSKishore Padmanabha blob->data[i + j] = blob->data[i + j + word_size]; 8377e604e7fSKishore Padmanabha blob->data[i + j + word_size] = xchar; 8387e604e7fSKishore Padmanabha } 8397e604e7fSKishore Padmanabha } 8407e604e7fSKishore Padmanabha } 8417e604e7fSKishore Padmanabha 8427e604e7fSKishore Padmanabha /* 8437e604e7fSKishore Padmanabha * Perform the blob buffer 64 bit byte swap. 8447e604e7fSKishore Padmanabha * This api makes the first byte the last in 8457e604e7fSKishore Padmanabha * a given 64 bit value and vice-versa. 8467e604e7fSKishore Padmanabha * 8477e604e7fSKishore Padmanabha * blob [in] The blob's data to be used for swap. 8487e604e7fSKishore Padmanabha * 8497e604e7fSKishore Padmanabha * returns void. 8507e604e7fSKishore Padmanabha */ 8517e604e7fSKishore Padmanabha void 8527e604e7fSKishore Padmanabha ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob) 8537e604e7fSKishore Padmanabha { 8547e604e7fSKishore Padmanabha uint32_t i, j, num; 8557e604e7fSKishore Padmanabha uint8_t xchar; 8567e604e7fSKishore Padmanabha uint32_t offset = ULP_64B_IN_BYTES - 1; 8577e604e7fSKishore Padmanabha 8587e604e7fSKishore Padmanabha /* validate the arguments */ 8597e604e7fSKishore Padmanabha if (!blob) { 860dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 8617e604e7fSKishore Padmanabha return; /* failure */ 8627e604e7fSKishore Padmanabha } 8637e604e7fSKishore Padmanabha num = ULP_BITS_2_BYTE(blob->write_idx); 8647e604e7fSKishore Padmanabha for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) { 8657e604e7fSKishore Padmanabha for (j = 0; j < (ULP_64B_IN_BYTES / 2); j++) { 8667e604e7fSKishore Padmanabha xchar = blob->data[i + j]; 8677e604e7fSKishore Padmanabha blob->data[i + j] = blob->data[i + offset - j]; 8687e604e7fSKishore Padmanabha blob->data[i + offset - j] = xchar; 8697e604e7fSKishore Padmanabha } 8707e604e7fSKishore Padmanabha } 8717e604e7fSKishore Padmanabha } 8727e604e7fSKishore Padmanabha 8733fe124d2SKishore Padmanabha static int32_t 8743fe124d2SKishore Padmanabha ulp_blob_msb_block_merge(struct ulp_blob *dst, struct ulp_blob *src, 8753fe124d2SKishore Padmanabha uint32_t block_size, uint32_t pad) 8763fe124d2SKishore Padmanabha { 8773fe124d2SKishore Padmanabha uint32_t i, k, write_bytes, remaining; 8783fe124d2SKishore Padmanabha uint16_t num; 8793fe124d2SKishore Padmanabha uint8_t *src_buf = ulp_blob_data_get(src, &num); 8803fe124d2SKishore Padmanabha uint8_t bluff; 8813fe124d2SKishore Padmanabha 8823fe124d2SKishore Padmanabha for (i = 0; i < num;) { 8833fe124d2SKishore Padmanabha if (((dst->write_idx % block_size) + (num - i)) > block_size) 884dbd29c42SKishore Padmanabha write_bytes = block_size - 885dbd29c42SKishore Padmanabha (dst->write_idx % block_size); 8863fe124d2SKishore Padmanabha else 8873fe124d2SKishore Padmanabha write_bytes = num - i; 8883fe124d2SKishore Padmanabha for (k = 0; k < ULP_BITS_2_BYTE_NR(write_bytes); k++) { 8893fe124d2SKishore Padmanabha ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE, 8903fe124d2SKishore Padmanabha *src_buf); 8913fe124d2SKishore Padmanabha dst->write_idx += ULP_BLOB_BYTE; 8923fe124d2SKishore Padmanabha src_buf++; 8933fe124d2SKishore Padmanabha } 8943fe124d2SKishore Padmanabha remaining = write_bytes % ULP_BLOB_BYTE; 8953fe124d2SKishore Padmanabha if (remaining) { 8963fe124d2SKishore Padmanabha bluff = (*src_buf) & ((uint8_t)-1 << 8973fe124d2SKishore Padmanabha (ULP_BLOB_BYTE - remaining)); 8983fe124d2SKishore Padmanabha ulp_bs_put_msb(dst->data, dst->write_idx, 8993fe124d2SKishore Padmanabha ULP_BLOB_BYTE, bluff); 9003fe124d2SKishore Padmanabha dst->write_idx += remaining; 9013fe124d2SKishore Padmanabha } 9023fe124d2SKishore Padmanabha if (write_bytes != (num - i)) { 9033fe124d2SKishore Padmanabha /* add the padding */ 9043fe124d2SKishore Padmanabha ulp_blob_pad_push(dst, pad); 9053fe124d2SKishore Padmanabha if (remaining) { 9063fe124d2SKishore Padmanabha ulp_bs_put_msb(dst->data, dst->write_idx, 9073fe124d2SKishore Padmanabha ULP_BLOB_BYTE - remaining, 9083fe124d2SKishore Padmanabha *src_buf); 9093fe124d2SKishore Padmanabha dst->write_idx += ULP_BLOB_BYTE - remaining; 9103fe124d2SKishore Padmanabha src_buf++; 9113fe124d2SKishore Padmanabha } 9123fe124d2SKishore Padmanabha } 9133fe124d2SKishore Padmanabha i += write_bytes; 9143fe124d2SKishore Padmanabha } 9153fe124d2SKishore Padmanabha return 0; 9163fe124d2SKishore Padmanabha } 9173fe124d2SKishore Padmanabha 9183fe124d2SKishore Padmanabha /* 9193fe124d2SKishore Padmanabha * Perform the blob buffer merge. 9203fe124d2SKishore Padmanabha * This api makes the src blob merged to the dst blob. 9213fe124d2SKishore Padmanabha * The block size and pad size help in padding the dst blob 9223fe124d2SKishore Padmanabha * 9233fe124d2SKishore Padmanabha * dst [in] The destination blob, the blob to be merged. 9243fe124d2SKishore Padmanabha * src [in] The src blob. 925dd0191d5SShuanglin Wang * block_size [in] The size of the block in bytes after which padding gets 926dd0191d5SShuanglin Wang * applied. 9273fe124d2SKishore Padmanabha * pad [in] The size of the pad to be applied. 9283fe124d2SKishore Padmanabha * 9293fe124d2SKishore Padmanabha * returns 0 on success. 9303fe124d2SKishore Padmanabha */ 9313fe124d2SKishore Padmanabha int32_t 9323fe124d2SKishore Padmanabha ulp_blob_block_merge(struct ulp_blob *dst, struct ulp_blob *src, 9333fe124d2SKishore Padmanabha uint32_t block_size, uint32_t pad) 9343fe124d2SKishore Padmanabha { 9353fe124d2SKishore Padmanabha if (dst->byte_order == BNXT_ULP_BYTE_ORDER_BE && 9363fe124d2SKishore Padmanabha src->byte_order == BNXT_ULP_BYTE_ORDER_BE) 9373fe124d2SKishore Padmanabha return ulp_blob_msb_block_merge(dst, src, block_size, pad); 9383fe124d2SKishore Padmanabha 939dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "block merge not implemented yet\n"); 9403fe124d2SKishore Padmanabha return -EINVAL; 9413fe124d2SKishore Padmanabha } 9423fe124d2SKishore Padmanabha 9433fe124d2SKishore Padmanabha int32_t 9443fe124d2SKishore Padmanabha ulp_blob_append(struct ulp_blob *dst, struct ulp_blob *src, 9453fe124d2SKishore Padmanabha uint16_t src_offset, uint16_t src_len) 9463fe124d2SKishore Padmanabha { 947dd0191d5SShuanglin Wang uint32_t k, remaining = 0; 9483fe124d2SKishore Padmanabha uint16_t num; 9493fe124d2SKishore Padmanabha uint8_t bluff; 9503fe124d2SKishore Padmanabha uint8_t *src_buf = ulp_blob_data_get(src, &num); 9513fe124d2SKishore Padmanabha 9523fe124d2SKishore Padmanabha if ((src_offset + src_len) > num) 9533fe124d2SKishore Padmanabha return -EINVAL; 9543fe124d2SKishore Padmanabha 9553fe124d2SKishore Padmanabha /* Only supporting BE for now */ 9563fe124d2SKishore Padmanabha if (src->byte_order != BNXT_ULP_BYTE_ORDER_BE || 9573fe124d2SKishore Padmanabha dst->byte_order != BNXT_ULP_BYTE_ORDER_BE) 9583fe124d2SKishore Padmanabha return -EINVAL; 9593fe124d2SKishore Padmanabha 9603fe124d2SKishore Padmanabha /* Handle if the source offset is not on a byte boundary */ 9613fe124d2SKishore Padmanabha remaining = src_offset % ULP_BLOB_BYTE; 9623fe124d2SKishore Padmanabha if (remaining) { 9633fe124d2SKishore Padmanabha bluff = src_buf[src_offset / ULP_BLOB_BYTE] & ((uint8_t)-1 >> 9643fe124d2SKishore Padmanabha (ULP_BLOB_BYTE - remaining)); 9653fe124d2SKishore Padmanabha ulp_bs_put_msb(dst->data, dst->write_idx, 9663fe124d2SKishore Padmanabha ULP_BLOB_BYTE, bluff); 9673fe124d2SKishore Padmanabha dst->write_idx += remaining; 9682730e7f9SKishore Padmanabha src_offset += remaining; 9693fe124d2SKishore Padmanabha } 9703fe124d2SKishore Padmanabha 9712730e7f9SKishore Padmanabha src_buf += ULP_BITS_2_BYTE_NR(src_offset); 9722730e7f9SKishore Padmanabha 9733fe124d2SKishore Padmanabha /* Push the byte aligned pieces */ 9743fe124d2SKishore Padmanabha for (k = 0; k < ULP_BITS_2_BYTE_NR(src_len); k++) { 9753fe124d2SKishore Padmanabha ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE, 9763fe124d2SKishore Padmanabha *src_buf); 9773fe124d2SKishore Padmanabha dst->write_idx += ULP_BLOB_BYTE; 9783fe124d2SKishore Padmanabha src_buf++; 9793fe124d2SKishore Padmanabha } 9803fe124d2SKishore Padmanabha 9813fe124d2SKishore Padmanabha /* Handle the remaining if length is not a byte boundary */ 982dd0191d5SShuanglin Wang if (src_len > remaining) 983dd0191d5SShuanglin Wang remaining = (src_len - remaining) % ULP_BLOB_BYTE; 984dd0191d5SShuanglin Wang else 985dd0191d5SShuanglin Wang remaining = 0; 9863fe124d2SKishore Padmanabha if (remaining) { 9873fe124d2SKishore Padmanabha bluff = (*src_buf) & ((uint8_t)-1 << 9883fe124d2SKishore Padmanabha (ULP_BLOB_BYTE - remaining)); 9893fe124d2SKishore Padmanabha ulp_bs_put_msb(dst->data, dst->write_idx, 9903fe124d2SKishore Padmanabha ULP_BLOB_BYTE, bluff); 9913fe124d2SKishore Padmanabha dst->write_idx += remaining; 9923fe124d2SKishore Padmanabha } 9933fe124d2SKishore Padmanabha 9943fe124d2SKishore Padmanabha return 0; 9953fe124d2SKishore Padmanabha } 9963fe124d2SKishore Padmanabha 9977e604e7fSKishore Padmanabha /* 998f63aa27dSKishore Padmanabha * Perform the blob buffer copy. 999f63aa27dSKishore Padmanabha * This api makes the src blob merged to the dst blob. 1000f63aa27dSKishore Padmanabha * 1001f63aa27dSKishore Padmanabha * dst [in] The destination blob, the blob to be merged. 1002f63aa27dSKishore Padmanabha * src [in] The src blob. 1003f63aa27dSKishore Padmanabha * 1004f63aa27dSKishore Padmanabha * returns 0 on success. 1005f63aa27dSKishore Padmanabha */ 1006f63aa27dSKishore Padmanabha int32_t 1007f63aa27dSKishore Padmanabha ulp_blob_buffer_copy(struct ulp_blob *dst, struct ulp_blob *src) 1008f63aa27dSKishore Padmanabha { 1009f63aa27dSKishore Padmanabha if ((dst->write_idx + src->write_idx) > dst->bitlen) { 1010dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "source buffer too large\n"); 1011f63aa27dSKishore Padmanabha return -EINVAL; 1012f63aa27dSKishore Padmanabha } 1013f63aa27dSKishore Padmanabha if (ULP_BITS_IS_BYTE_NOT_ALIGNED(dst->write_idx) || 1014f63aa27dSKishore Padmanabha ULP_BITS_IS_BYTE_NOT_ALIGNED(src->write_idx)) { 1015dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "source buffer is not aligned\n"); 1016f63aa27dSKishore Padmanabha return -EINVAL; 1017f63aa27dSKishore Padmanabha } 1018f63aa27dSKishore Padmanabha memcpy(&dst->data[ULP_BITS_2_BYTE_NR(dst->write_idx)], 1019f63aa27dSKishore Padmanabha src->data, ULP_BITS_2_BYTE_NR(src->write_idx)); 1020f63aa27dSKishore Padmanabha dst->write_idx += src->write_idx; 1021f63aa27dSKishore Padmanabha return 0; 1022f63aa27dSKishore Padmanabha } 1023f63aa27dSKishore Padmanabha 1024f63aa27dSKishore Padmanabha /* 102588badb3aSMike Baucom * Read data from the operand 102688badb3aSMike Baucom * 102788badb3aSMike Baucom * operand [in] A pointer to a 16 Byte operand 102888badb3aSMike Baucom * 102988badb3aSMike Baucom * val [in/out] The variable to copy the operand to 103088badb3aSMike Baucom * 103188badb3aSMike Baucom * bytes [in] The number of bytes to read into val 103288badb3aSMike Baucom * 1033*c569279aSShuanglin Wang * returns zero on success. 103488badb3aSMike Baucom */ 1035*c569279aSShuanglin Wang int32_t 103688badb3aSMike Baucom ulp_operand_read(uint8_t *operand, 103788badb3aSMike Baucom uint8_t *val, 103888badb3aSMike Baucom uint16_t bytes) 103988badb3aSMike Baucom { 104088badb3aSMike Baucom /* validate the arguments */ 104188badb3aSMike Baucom if (!operand || !val) { 1042dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "invalid argument\n"); 1043*c569279aSShuanglin Wang return -EINVAL; 104488badb3aSMike Baucom } 104588badb3aSMike Baucom memcpy(val, operand, bytes); 1046*c569279aSShuanglin Wang return 0; 104788badb3aSMike Baucom } 104888badb3aSMike Baucom 104988badb3aSMike Baucom /* 105088badb3aSMike Baucom * Check the buffer is empty 105188badb3aSMike Baucom * 105288badb3aSMike Baucom * buf [in] The buffer 105388badb3aSMike Baucom * size [in] The size of the buffer 105488badb3aSMike Baucom * 105588badb3aSMike Baucom */ 105688badb3aSMike Baucom int32_t ulp_buffer_is_empty(const uint8_t *buf, uint32_t size) 105788badb3aSMike Baucom { 105888badb3aSMike Baucom return buf[0] == 0 && !memcmp(buf, buf + 1, size - 1); 105988badb3aSMike Baucom } 10602bbcdee8SKishore Padmanabha 10612bbcdee8SKishore Padmanabha /* Function to check if bitmap is zero.Return 1 on success */ 10622bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_is_zero(uint8_t *bitmap, int32_t size) 10632bbcdee8SKishore Padmanabha { 10642bbcdee8SKishore Padmanabha while (size-- > 0) { 10652bbcdee8SKishore Padmanabha if (*bitmap != 0) 10662bbcdee8SKishore Padmanabha return 0; 10672bbcdee8SKishore Padmanabha bitmap++; 10682bbcdee8SKishore Padmanabha } 10692bbcdee8SKishore Padmanabha return 1; 10702bbcdee8SKishore Padmanabha } 10712bbcdee8SKishore Padmanabha 10722bbcdee8SKishore Padmanabha /* Function to check if bitmap is ones. Return 1 on success */ 10732bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size) 10742bbcdee8SKishore Padmanabha { 10752bbcdee8SKishore Padmanabha while (size-- > 0) { 10762bbcdee8SKishore Padmanabha if (*bitmap != 0xFF) 10772bbcdee8SKishore Padmanabha return 0; 10782bbcdee8SKishore Padmanabha bitmap++; 10792bbcdee8SKishore Padmanabha } 10802bbcdee8SKishore Padmanabha return 1; 10812bbcdee8SKishore Padmanabha } 10822bbcdee8SKishore Padmanabha 10832bbcdee8SKishore Padmanabha /* Function to check if bitmap is not zero. Return 1 on success */ 1084741172beSKishore Padmanabha uint32_t ulp_bitmap_notzero(const uint8_t *bitmap, int32_t size) 10852bbcdee8SKishore Padmanabha { 10862bbcdee8SKishore Padmanabha while (size-- > 0) { 10872bbcdee8SKishore Padmanabha if (*bitmap != 0) 10882bbcdee8SKishore Padmanabha return 1; 10892bbcdee8SKishore Padmanabha bitmap++; 10902bbcdee8SKishore Padmanabha } 10912bbcdee8SKishore Padmanabha return 0; 10922bbcdee8SKishore Padmanabha } 10930001cc58SKishore Padmanabha 10940001cc58SKishore Padmanabha /* returns 0 if input is power of 2 */ 10950001cc58SKishore Padmanabha int32_t ulp_util_is_power_of_2(uint64_t x) 10960001cc58SKishore Padmanabha { 10970001cc58SKishore Padmanabha if (((x - 1) & x)) 10980001cc58SKishore Padmanabha return -1; 10990001cc58SKishore Padmanabha return 0; 11000001cc58SKishore Padmanabha } 1101