188badb3aSMike Baucom /* SPDX-License-Identifier: BSD-3-Clause 2e6e8f03eSRandy Schacher * Copyright(c) 2014-2023 Broadcom 388badb3aSMike Baucom * All rights reserved. 488badb3aSMike Baucom */ 588badb3aSMike Baucom 688badb3aSMike Baucom #ifndef _ULP_UTILS_H_ 788badb3aSMike Baucom #define _ULP_UTILS_H_ 888badb3aSMike Baucom 988badb3aSMike Baucom #include "bnxt.h" 108ce17d56SKishore Padmanabha #include "ulp_template_db_enum.h" 1188badb3aSMike Baucom 123fe124d2SKishore Padmanabha #define ULP_BUFFER_ALIGN_8_BITS 8 139238ac2aSKishore Padmanabha #define ULP_BUFFER_ALIGN_8_BYTE 8 149238ac2aSKishore Padmanabha #define ULP_BUFFER_ALIGN_16_BYTE 16 15f4a4421cSKishore Padmanabha #define ULP_BUFFER_ALIGN_64_BYTE 64 167e604e7fSKishore Padmanabha #define ULP_64B_IN_BYTES 8 17af50070eSKishore Padmanabha #define ULP_64B_IN_BITS 64 183fe124d2SKishore Padmanabha 1988badb3aSMike Baucom /* 2088badb3aSMike Baucom * Macros for bitmap sets and gets 2188badb3aSMike Baucom * These macros can be used if the val are power of 2. 2288badb3aSMike Baucom */ 2388badb3aSMike Baucom #define ULP_BITMAP_SET(bitmap, val) ((bitmap) |= (val)) 2488badb3aSMike Baucom #define ULP_BITMAP_RESET(bitmap, val) ((bitmap) &= ~(val)) 2588badb3aSMike Baucom #define ULP_BITMAP_ISSET(bitmap, val) ((bitmap) & (val)) 262bbcdee8SKishore Padmanabha #define ULP_BITMAP_CMP(b1, b2) memcmp(&(b1)->bits, \ 2788badb3aSMike Baucom &(b2)->bits, sizeof((b1)->bits)) 2888badb3aSMike Baucom /* 2988badb3aSMike Baucom * Macros for bitmap sets and gets 3088badb3aSMike Baucom * These macros can be used if the val are not power of 2 and 3188badb3aSMike Baucom * are simple index values. 3288badb3aSMike Baucom */ 3388badb3aSMike Baucom #define ULP_INDEX_BITMAP_SIZE (sizeof(uint64_t) * 8) 3488badb3aSMike Baucom #define ULP_INDEX_BITMAP_CSET(i) (1UL << \ 3588badb3aSMike Baucom ((ULP_INDEX_BITMAP_SIZE - 1) - \ 3688badb3aSMike Baucom ((i) % ULP_INDEX_BITMAP_SIZE))) 3788badb3aSMike Baucom 3888badb3aSMike Baucom #define ULP_INDEX_BITMAP_SET(b, i) ((b) |= \ 3988badb3aSMike Baucom (1UL << ((ULP_INDEX_BITMAP_SIZE - 1) - \ 4088badb3aSMike Baucom ((i) % ULP_INDEX_BITMAP_SIZE)))) 4188badb3aSMike Baucom 4288badb3aSMike Baucom #define ULP_INDEX_BITMAP_RESET(b, i) ((b) &= \ 4388badb3aSMike Baucom (~(1UL << ((ULP_INDEX_BITMAP_SIZE - 1) - \ 4488badb3aSMike Baucom ((i) % ULP_INDEX_BITMAP_SIZE))))) 4588badb3aSMike Baucom 4688badb3aSMike Baucom #define ULP_INDEX_BITMAP_GET(b, i) (((b) >> \ 4788badb3aSMike Baucom ((ULP_INDEX_BITMAP_SIZE - 1) - \ 4888badb3aSMike Baucom ((i) % ULP_INDEX_BITMAP_SIZE))) & 1) 4988badb3aSMike Baucom 5088badb3aSMike Baucom #define ULP_DEVICE_PARAMS_INDEX(tid, dev_id) \ 5188badb3aSMike Baucom (((tid) << BNXT_ULP_LOG2_MAX_NUM_DEV) | (dev_id)) 5288badb3aSMike Baucom 5388badb3aSMike Baucom /* Macro to convert bytes to bits */ 5488badb3aSMike Baucom #define ULP_BYTE_2_BITS(byte_x) ((byte_x) * 8) 5588badb3aSMike Baucom /* Macro to convert bits to bytes */ 5688badb3aSMike Baucom #define ULP_BITS_2_BYTE(bits_x) (((bits_x) + 7) / 8) 5788badb3aSMike Baucom /* Macro to convert bits to bytes with no round off*/ 5888badb3aSMike Baucom #define ULP_BITS_2_BYTE_NR(bits_x) ((bits_x) / 8) 5988badb3aSMike Baucom 60f4a4421cSKishore Padmanabha /* Macro to round off to next multiple of 8*/ 61f4a4421cSKishore Padmanabha #define ULP_BYTE_ROUND_OFF_8(x) (((x) + 7) & ~7) 62f4a4421cSKishore Padmanabha 637e604e7fSKishore Padmanabha /* Macro to check bits are byte aligned */ 647e604e7fSKishore Padmanabha #define ULP_BITS_IS_BYTE_NOT_ALIGNED(x) ((x) % 8) 657e604e7fSKishore Padmanabha 66dd0191d5SShuanglin Wang /* Macro for word conversion */ 67dd0191d5SShuanglin Wang #define ULP_BITS_TO_4_BYTE_WORD(x) (((x) + 31) / 32) 68dd0191d5SShuanglin Wang #define ULP_BITS_TO_32_BYTE_WORD(x) (((x) + 255) / 256) 69dd0191d5SShuanglin Wang #define ULP_BITS_TO_4_BYTE_QWORDS(x) (((x) + 127) / 128) 70dd0191d5SShuanglin Wang #define ULP_BITS_TO_128B_ALIGNED_BYTES(x) ((((x) + 127) / 128) * 16) 71dd0191d5SShuanglin Wang 722bbcdee8SKishore Padmanabha /* Macros to read the computed fields */ 730f772db6SKishore Padmanabha #define ULP_COMP_FLD_IDX_RD(params, idx) \ 741993b267SShahaji Bhosle rte_be_to_cpu_64((params)->comp_fld[(idx)]) 752bbcdee8SKishore Padmanabha 760f772db6SKishore Padmanabha #define ULP_COMP_FLD_IDX_WR(params, idx, val) \ 771993b267SShahaji Bhosle ((params)->comp_fld[(idx)] = rte_cpu_to_be_64((uint64_t)(val))) 7888badb3aSMike Baucom /* 7988badb3aSMike Baucom * Making the blob statically sized to 128 bytes for now. 8088badb3aSMike Baucom * The blob must be initialized with ulp_blob_init prior to using. 8188badb3aSMike Baucom */ 8288badb3aSMike Baucom #define BNXT_ULP_FLMP_BLOB_SIZE (128) 8388badb3aSMike Baucom #define BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS ULP_BYTE_2_BITS(BNXT_ULP_FLMP_BLOB_SIZE) 8488badb3aSMike Baucom struct ulp_blob { 8588badb3aSMike Baucom enum bnxt_ulp_byte_order byte_order; 8688badb3aSMike Baucom uint16_t write_idx; 8788badb3aSMike Baucom uint16_t bitlen; 8888badb3aSMike Baucom uint8_t data[BNXT_ULP_FLMP_BLOB_SIZE]; 8988badb3aSMike Baucom uint16_t encap_swap_idx; 9088badb3aSMike Baucom }; 9188badb3aSMike Baucom 9288badb3aSMike Baucom /* 9388badb3aSMike Baucom * The data can likely be only 32 bits for now. Just size check 9488badb3aSMike Baucom * the data when being written. 9588badb3aSMike Baucom */ 9688badb3aSMike Baucom #define ULP_REGFILE_ENTRY_SIZE (sizeof(uint32_t)) 9788badb3aSMike Baucom struct ulp_regfile_entry { 9888badb3aSMike Baucom uint64_t data; 9988badb3aSMike Baucom uint32_t size; 10088badb3aSMike Baucom }; 10188badb3aSMike Baucom 10288badb3aSMike Baucom struct ulp_regfile { 103a2417601SKishore Padmanabha struct ulp_regfile_entry entry[BNXT_ULP_RF_IDX_LAST]; 10488badb3aSMike Baucom }; 10588badb3aSMike Baucom 10688badb3aSMike Baucom /* 10788badb3aSMike Baucom * Initialize the regfile structure for writing 10888badb3aSMike Baucom * 10988badb3aSMike Baucom * regfile [in] Ptr to a regfile instance 11088badb3aSMike Baucom * 111c569279aSShuanglin Wang * returns zero on success 11288badb3aSMike Baucom */ 113*0c036a14SPeter Spreadborough static inline int32_t 114*0c036a14SPeter Spreadborough ulp_regfile_init(struct ulp_regfile *regfile) 115*0c036a14SPeter Spreadborough { 116*0c036a14SPeter Spreadborough /* validate the arguments */ 117*0c036a14SPeter Spreadborough if (!regfile) { 118*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 119*0c036a14SPeter Spreadborough return -EINVAL; 120*0c036a14SPeter Spreadborough } 121*0c036a14SPeter Spreadborough memset(regfile, 0, sizeof(struct ulp_regfile)); 122*0c036a14SPeter Spreadborough return 0; /* Success */ 123*0c036a14SPeter Spreadborough } 12488badb3aSMike Baucom 12588badb3aSMike Baucom /* 12688badb3aSMike Baucom * Read a value from the regfile 12788badb3aSMike Baucom * 12888badb3aSMike Baucom * regfile [in] The regfile instance. Must be initialized prior to being used 12988badb3aSMike Baucom * 13088badb3aSMike Baucom * field [in] The field to be read within the regfile. 13188badb3aSMike Baucom * 132*0c036a14SPeter Spreadborough * data [in/out] 133*0c036a14SPeter Spreadborough * 134c569279aSShuanglin Wang * returns zero on success 13588badb3aSMike Baucom */ 136*0c036a14SPeter Spreadborough static inline int32_t 13788badb3aSMike Baucom ulp_regfile_read(struct ulp_regfile *regfile, 138a2417601SKishore Padmanabha enum bnxt_ulp_rf_idx field, 139*0c036a14SPeter Spreadborough uint64_t *data) 140*0c036a14SPeter Spreadborough { 141*0c036a14SPeter Spreadborough /* validate the arguments */ 142*0c036a14SPeter Spreadborough if (unlikely(!regfile || field >= BNXT_ULP_RF_IDX_LAST)) { 143*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 144*0c036a14SPeter Spreadborough return -EINVAL; 145*0c036a14SPeter Spreadborough } 146*0c036a14SPeter Spreadborough 147*0c036a14SPeter Spreadborough *data = regfile->entry[field].data; 148*0c036a14SPeter Spreadborough return 0; 149*0c036a14SPeter Spreadborough } 15088badb3aSMike Baucom 15188badb3aSMike Baucom /* 15288badb3aSMike Baucom * Write a value to the regfile 15388badb3aSMike Baucom * 15488badb3aSMike Baucom * regfile [in] The regfile instance. Must be initialized prior to being used 15588badb3aSMike Baucom * 15688badb3aSMike Baucom * field [in] The field to be written within the regfile. 15788badb3aSMike Baucom * 15888badb3aSMike Baucom * data [in] The value is written into this variable. It is going to be in the 15988badb3aSMike Baucom * same byte order as it was written. 16088badb3aSMike Baucom * 161*0c036a14SPeter Spreadborough * size [in] The size in bytes of the value being written into this 162*0c036a14SPeter Spreadborough * variable. 163*0c036a14SPeter Spreadborough * 164*0c036a14SPeter Spreadborough * returns 0 on success 16588badb3aSMike Baucom */ 166*0c036a14SPeter Spreadborough static inline int32_t 16788badb3aSMike Baucom ulp_regfile_write(struct ulp_regfile *regfile, 168a2417601SKishore Padmanabha enum bnxt_ulp_rf_idx field, 169*0c036a14SPeter Spreadborough uint64_t data) 170*0c036a14SPeter Spreadborough { 171*0c036a14SPeter Spreadborough /* validate the arguments */ 172*0c036a14SPeter Spreadborough if (unlikely(!regfile || field >= BNXT_ULP_RF_IDX_LAST)) { 173*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 174*0c036a14SPeter Spreadborough return -EINVAL; /* failure */ 175*0c036a14SPeter Spreadborough } 176*0c036a14SPeter Spreadborough 177*0c036a14SPeter Spreadborough regfile->entry[field].data = data; 178*0c036a14SPeter Spreadborough return 0; /* Success */ 179*0c036a14SPeter Spreadborough } 180*0c036a14SPeter Spreadborough 181*0c036a14SPeter Spreadborough 182*0c036a14SPeter Spreadborough /* 183*0c036a14SPeter Spreadborough * Add data to the byte array in Big endian format. 184*0c036a14SPeter Spreadborough * 185*0c036a14SPeter Spreadborough * bs [in] The byte array where data is pushed 186*0c036a14SPeter Spreadborough * 187*0c036a14SPeter Spreadborough * bitpos [in] The offset where data is pushed 188*0c036a14SPeter Spreadborough * 189*0c036a14SPeter Spreadborough * bitlen [in] The number of bits to be added to the data array. 190*0c036a14SPeter Spreadborough * 191*0c036a14SPeter Spreadborough * val [in] The data to be added to the data array. 192*0c036a14SPeter Spreadborough * 193*0c036a14SPeter Spreadborough */ 194*0c036a14SPeter Spreadborough static inline void 195*0c036a14SPeter Spreadborough ulp_bs_put_msb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val) 196*0c036a14SPeter Spreadborough { 197*0c036a14SPeter Spreadborough uint8_t bitoffs = bitpos % 8; 198*0c036a14SPeter Spreadborough uint16_t index = bitpos / 8; 199*0c036a14SPeter Spreadborough uint8_t mask; 200*0c036a14SPeter Spreadborough uint8_t tmp; 201*0c036a14SPeter Spreadborough int8_t shift; 202*0c036a14SPeter Spreadborough 203*0c036a14SPeter Spreadborough tmp = bs[index]; 204*0c036a14SPeter Spreadborough mask = ((uint8_t)-1 >> (8 - bitlen)); 205*0c036a14SPeter Spreadborough shift = 8 - bitoffs - bitlen; 206*0c036a14SPeter Spreadborough val &= mask; 207*0c036a14SPeter Spreadborough 208*0c036a14SPeter Spreadborough if (shift >= 0) { 209*0c036a14SPeter Spreadborough tmp &= ~(mask << shift); 210*0c036a14SPeter Spreadborough tmp |= val << shift; 211*0c036a14SPeter Spreadborough bs[index] = tmp; 212*0c036a14SPeter Spreadborough } else { 213*0c036a14SPeter Spreadborough tmp &= ~((uint8_t)-1 >> bitoffs); 214*0c036a14SPeter Spreadborough tmp |= val >> -shift; 215*0c036a14SPeter Spreadborough bs[index++] = tmp; 216*0c036a14SPeter Spreadborough 217*0c036a14SPeter Spreadborough tmp = bs[index]; 218*0c036a14SPeter Spreadborough tmp &= ((uint8_t)-1 >> (bitlen - (8 - bitoffs))); 219*0c036a14SPeter Spreadborough tmp |= val << (8 + shift); 220*0c036a14SPeter Spreadborough bs[index] = tmp; 221*0c036a14SPeter Spreadborough } 222*0c036a14SPeter Spreadborough } 223*0c036a14SPeter Spreadborough 224*0c036a14SPeter Spreadborough /* 225*0c036a14SPeter Spreadborough * Add data to the byte array in Little endian format. 226*0c036a14SPeter Spreadborough * 227*0c036a14SPeter Spreadborough * bs [in] The byte array where data is pushed 228*0c036a14SPeter Spreadborough * 229*0c036a14SPeter Spreadborough * bitpos [in] The offset where data is pushed 230*0c036a14SPeter Spreadborough * 231*0c036a14SPeter Spreadborough * bitlen [in] The number of bits to be added to the data array. 232*0c036a14SPeter Spreadborough * 233*0c036a14SPeter Spreadborough * val [in] The data to be added to the data array. 234*0c036a14SPeter Spreadborough * 235*0c036a14SPeter Spreadborough */ 236*0c036a14SPeter Spreadborough static inline void 237*0c036a14SPeter Spreadborough ulp_bs_put_lsb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val) 238*0c036a14SPeter Spreadborough { 239*0c036a14SPeter Spreadborough uint8_t bitoffs = bitpos % 8; 240*0c036a14SPeter Spreadborough uint16_t index = bitpos / 8; 241*0c036a14SPeter Spreadborough uint8_t mask; 242*0c036a14SPeter Spreadborough uint8_t tmp; 243*0c036a14SPeter Spreadborough uint8_t shift; 244*0c036a14SPeter Spreadborough uint8_t partial; 245*0c036a14SPeter Spreadborough 246*0c036a14SPeter Spreadborough tmp = bs[index]; 247*0c036a14SPeter Spreadborough shift = bitoffs; 248*0c036a14SPeter Spreadborough 249*0c036a14SPeter Spreadborough if (bitoffs + bitlen <= 8) { 250*0c036a14SPeter Spreadborough mask = ((1 << bitlen) - 1) << shift; 251*0c036a14SPeter Spreadborough tmp &= ~mask; 252*0c036a14SPeter Spreadborough tmp |= ((val << shift) & mask); 253*0c036a14SPeter Spreadborough bs[index] = tmp; 254*0c036a14SPeter Spreadborough } else { 255*0c036a14SPeter Spreadborough partial = 8 - bitoffs; 256*0c036a14SPeter Spreadborough mask = ((1 << partial) - 1) << shift; 257*0c036a14SPeter Spreadborough tmp &= ~mask; 258*0c036a14SPeter Spreadborough tmp |= ((val << shift) & mask); 259*0c036a14SPeter Spreadborough bs[index++] = tmp; 260*0c036a14SPeter Spreadborough 261*0c036a14SPeter Spreadborough val >>= partial; 262*0c036a14SPeter Spreadborough partial = bitlen - partial; 263*0c036a14SPeter Spreadborough mask = ((1 << partial) - 1); 264*0c036a14SPeter Spreadborough tmp = bs[index]; 265*0c036a14SPeter Spreadborough tmp &= ~mask; 266*0c036a14SPeter Spreadborough tmp |= (val & mask); 267*0c036a14SPeter Spreadborough bs[index] = tmp; 268*0c036a14SPeter Spreadborough } 269*0c036a14SPeter Spreadborough } 27088badb3aSMike Baucom 27188badb3aSMike Baucom /* 272f634204bSKishore Padmanabha * Add data to the byte array in Little endian format. 273f634204bSKishore Padmanabha * 274f634204bSKishore Padmanabha * bs [in] The byte array where data is pushed 275f634204bSKishore Padmanabha * 276f634204bSKishore Padmanabha * pos [in] The offset where data is pushed 277f634204bSKishore Padmanabha * 278f634204bSKishore Padmanabha * len [in] The number of bits to be added to the data array. 279f634204bSKishore Padmanabha * 280f634204bSKishore Padmanabha * val [in] The data to be added to the data array. 281f634204bSKishore Padmanabha * 282f634204bSKishore Padmanabha * returns the number of bits pushed. 283f634204bSKishore Padmanabha */ 284*0c036a14SPeter Spreadborough static inline uint32_t 285*0c036a14SPeter Spreadborough ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val) 286*0c036a14SPeter Spreadborough { 287*0c036a14SPeter Spreadborough int i; 288*0c036a14SPeter Spreadborough int cnt = (len) / 8; 289*0c036a14SPeter Spreadborough int tlen = len; 290*0c036a14SPeter Spreadborough 291*0c036a14SPeter Spreadborough if (cnt > 0 && !(len % 8)) 292*0c036a14SPeter Spreadborough cnt -= 1; 293*0c036a14SPeter Spreadborough 294*0c036a14SPeter Spreadborough for (i = 0; i < cnt; i++) { 295*0c036a14SPeter Spreadborough ulp_bs_put_lsb(bs, pos, 8, val[cnt - i]); 296*0c036a14SPeter Spreadborough pos += 8; 297*0c036a14SPeter Spreadborough tlen -= 8; 298*0c036a14SPeter Spreadborough } 299*0c036a14SPeter Spreadborough 300*0c036a14SPeter Spreadborough /* Handle the remainder bits */ 301*0c036a14SPeter Spreadborough if (tlen) 302*0c036a14SPeter Spreadborough ulp_bs_put_lsb(bs, pos, tlen, val[0]); 303*0c036a14SPeter Spreadborough return len; 304*0c036a14SPeter Spreadborough } 305f634204bSKishore Padmanabha 306f634204bSKishore Padmanabha /* 307f634204bSKishore Padmanabha * Add data to the byte array in Big endian format. 308f634204bSKishore Padmanabha * 309f634204bSKishore Padmanabha * bs [in] The byte array where data is pushed 310f634204bSKishore Padmanabha * 311f634204bSKishore Padmanabha * pos [in] The offset where data is pushed 312f634204bSKishore Padmanabha * 313f634204bSKishore Padmanabha * len [in] The number of bits to be added to the data array. 314f634204bSKishore Padmanabha * 315f634204bSKishore Padmanabha * val [in] The data to be added to the data array. 316f634204bSKishore Padmanabha * 317f634204bSKishore Padmanabha * returns the number of bits pushed. 318f634204bSKishore Padmanabha */ 319*0c036a14SPeter Spreadborough static inline uint32_t 320*0c036a14SPeter Spreadborough ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val) 321*0c036a14SPeter Spreadborough { 322*0c036a14SPeter Spreadborough int i; 323*0c036a14SPeter Spreadborough int cnt = (len + 7) / 8; 324*0c036a14SPeter Spreadborough 325*0c036a14SPeter Spreadborough /* Handle any remainder bits */ 326*0c036a14SPeter Spreadborough int tmp = len % 8; 327*0c036a14SPeter Spreadborough 328*0c036a14SPeter Spreadborough if (!tmp) 329*0c036a14SPeter Spreadborough tmp = 8; 330*0c036a14SPeter Spreadborough 331*0c036a14SPeter Spreadborough ulp_bs_put_msb(bs, pos, tmp, val[0]); 332*0c036a14SPeter Spreadborough 333*0c036a14SPeter Spreadborough pos += tmp; 334*0c036a14SPeter Spreadborough 335*0c036a14SPeter Spreadborough for (i = 1; i < cnt; i++) { 336*0c036a14SPeter Spreadborough ulp_bs_put_msb(bs, pos, 8, val[i]); 337*0c036a14SPeter Spreadborough pos += 8; 338*0c036a14SPeter Spreadborough } 339*0c036a14SPeter Spreadborough 340*0c036a14SPeter Spreadborough return len; 341*0c036a14SPeter Spreadborough } 342f634204bSKishore Padmanabha 343f634204bSKishore Padmanabha /* 34488badb3aSMike Baucom * Initializes the blob structure for creating binary blob 34588badb3aSMike Baucom * 34688badb3aSMike Baucom * blob [in] The blob to be initialized 34788badb3aSMike Baucom * 34888badb3aSMike Baucom * bitlen [in] The bit length of the blob 34988badb3aSMike Baucom * 35088badb3aSMike Baucom * order [in] The byte order for the blob. Currently only supporting 35188badb3aSMike Baucom * big endian. All fields are packed with this order. 35288badb3aSMike Baucom * 353c569279aSShuanglin Wang * returns zero on success 354*0c036a14SPeter Spreadborough * Notes - If bitlen is zero then set it to max. 35588badb3aSMike Baucom */ 356*0c036a14SPeter Spreadborough static inline int32_t 35788badb3aSMike Baucom ulp_blob_init(struct ulp_blob *blob, 35888badb3aSMike Baucom uint16_t bitlen, 359*0c036a14SPeter Spreadborough enum bnxt_ulp_byte_order order) 360*0c036a14SPeter Spreadborough { 361*0c036a14SPeter Spreadborough /* validate the arguments */ 362*0c036a14SPeter Spreadborough if (unlikely(!blob || bitlen > (8 * sizeof(blob->data)))) { 363*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 364*0c036a14SPeter Spreadborough return -EINVAL; 365*0c036a14SPeter Spreadborough } 366*0c036a14SPeter Spreadborough if (bitlen) 367*0c036a14SPeter Spreadborough blob->bitlen = bitlen; 368*0c036a14SPeter Spreadborough else 369*0c036a14SPeter Spreadborough blob->bitlen = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 370*0c036a14SPeter Spreadborough blob->byte_order = order; 371*0c036a14SPeter Spreadborough blob->write_idx = 0; 372*0c036a14SPeter Spreadborough memset(blob->data, 0, sizeof(blob->data)); 373*0c036a14SPeter Spreadborough return 0; /* Success */ 374*0c036a14SPeter Spreadborough } 37588badb3aSMike Baucom 37688badb3aSMike Baucom /* 37788badb3aSMike Baucom * Add data to the binary blob at the current offset. 37888badb3aSMike Baucom * 37988badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 38088badb3aSMike Baucom * be initialized prior to pushing data. 38188badb3aSMike Baucom * 38288badb3aSMike Baucom * data [in] A pointer to bytes to be added to the blob. 38388badb3aSMike Baucom * 38488badb3aSMike Baucom * datalen [in] The number of bits to be added to the blob. 38588badb3aSMike Baucom * 38688badb3aSMike Baucom * The offset of the data is updated after each push of data. 387c569279aSShuanglin Wang * 388c569279aSShuanglin Wang * returns zero on success 38988badb3aSMike Baucom */ 390*0c036a14SPeter Spreadborough #define ULP_BLOB_BYTE 8 391*0c036a14SPeter Spreadborough #define ULP_BLOB_BYTE_HEX 0xFF 392*0c036a14SPeter Spreadborough #define BLOB_MASK_CAL(x) ((0xFF << (x)) & 0xFF) 393*0c036a14SPeter Spreadborough static inline int32_t 39488badb3aSMike Baucom ulp_blob_push(struct ulp_blob *blob, 39588badb3aSMike Baucom uint8_t *data, 396*0c036a14SPeter Spreadborough uint32_t datalen) 397*0c036a14SPeter Spreadborough { 398*0c036a14SPeter Spreadborough uint32_t rc; 399*0c036a14SPeter Spreadborough 400*0c036a14SPeter Spreadborough /* validate the arguments */ 401*0c036a14SPeter Spreadborough if (unlikely(!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx))) { 402*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 403*0c036a14SPeter Spreadborough return -EINVAL; 404*0c036a14SPeter Spreadborough } 405*0c036a14SPeter Spreadborough 406*0c036a14SPeter Spreadborough if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) 407*0c036a14SPeter Spreadborough rc = ulp_bs_push_msb(blob->data, 408*0c036a14SPeter Spreadborough blob->write_idx, 409*0c036a14SPeter Spreadborough datalen, 410*0c036a14SPeter Spreadborough data); 411*0c036a14SPeter Spreadborough else 412*0c036a14SPeter Spreadborough rc = ulp_bs_push_lsb(blob->data, 413*0c036a14SPeter Spreadborough blob->write_idx, 414*0c036a14SPeter Spreadborough datalen, 415*0c036a14SPeter Spreadborough data); 416*0c036a14SPeter Spreadborough if (unlikely(!rc)) { 417*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "Failed to write blob\n"); 418*0c036a14SPeter Spreadborough return -EINVAL; 419*0c036a14SPeter Spreadborough } 420*0c036a14SPeter Spreadborough blob->write_idx += datalen; 421*0c036a14SPeter Spreadborough return 0; 422*0c036a14SPeter Spreadborough } 42388badb3aSMike Baucom 42488badb3aSMike Baucom /* 4257e604e7fSKishore Padmanabha * Insert data into the binary blob at the given offset. 4267e604e7fSKishore Padmanabha * 4277e604e7fSKishore Padmanabha * blob [in] The blob that data is added to. The blob must 4287e604e7fSKishore Padmanabha * be initialized prior to pushing data. 4297e604e7fSKishore Padmanabha * 4307e604e7fSKishore Padmanabha * offset [in] The offset where the data needs to be inserted. 4317e604e7fSKishore Padmanabha * 4327e604e7fSKishore Padmanabha * data [in/out] A pointer to bytes to be added to the blob. 4337e604e7fSKishore Padmanabha * 4347e604e7fSKishore Padmanabha * datalen [in] The number of bits to be added to the blob. 4357e604e7fSKishore Padmanabha * 4367e604e7fSKishore Padmanabha * The offset of the data is updated after each push of data. 437c569279aSShuanglin Wang * 438c569279aSShuanglin Wang * returns zero on success 4397e604e7fSKishore Padmanabha */ 440*0c036a14SPeter Spreadborough static inline int32_t 4417e604e7fSKishore Padmanabha ulp_blob_insert(struct ulp_blob *blob, uint32_t offset, 442*0c036a14SPeter Spreadborough uint8_t *data, uint32_t datalen) 443*0c036a14SPeter Spreadborough { 444*0c036a14SPeter Spreadborough uint32_t rc; 445*0c036a14SPeter Spreadborough uint8_t local_data[BNXT_ULP_FLMP_BLOB_SIZE]; 446*0c036a14SPeter Spreadborough uint16_t mov_len; 447*0c036a14SPeter Spreadborough 448*0c036a14SPeter Spreadborough /* validate the arguments */ 449*0c036a14SPeter Spreadborough if (unlikely(!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx) || 450*0c036a14SPeter Spreadborough offset > blob->write_idx)) { 451*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 452*0c036a14SPeter Spreadborough return -EINVAL; 453*0c036a14SPeter Spreadborough } 454*0c036a14SPeter Spreadborough 455*0c036a14SPeter Spreadborough mov_len = blob->write_idx - offset; 456*0c036a14SPeter Spreadborough /* If offset and data len are not 8 bit aligned then return error */ 457*0c036a14SPeter Spreadborough if (unlikely(ULP_BITS_IS_BYTE_NOT_ALIGNED(offset) || 458*0c036a14SPeter Spreadborough ULP_BITS_IS_BYTE_NOT_ALIGNED(datalen))) { 459*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument, not aligned\n"); 460*0c036a14SPeter Spreadborough return -EINVAL; 461*0c036a14SPeter Spreadborough } 462*0c036a14SPeter Spreadborough 463*0c036a14SPeter Spreadborough /* copy the data so we can move the data */ 464*0c036a14SPeter Spreadborough memcpy(local_data, &blob->data[ULP_BITS_2_BYTE_NR(offset)], 465*0c036a14SPeter Spreadborough ULP_BITS_2_BYTE(mov_len)); 466*0c036a14SPeter Spreadborough blob->write_idx = offset; 467*0c036a14SPeter Spreadborough if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) 468*0c036a14SPeter Spreadborough rc = ulp_bs_push_msb(blob->data, 469*0c036a14SPeter Spreadborough blob->write_idx, 470*0c036a14SPeter Spreadborough datalen, 471*0c036a14SPeter Spreadborough data); 472*0c036a14SPeter Spreadborough else 473*0c036a14SPeter Spreadborough rc = ulp_bs_push_lsb(blob->data, 474*0c036a14SPeter Spreadborough blob->write_idx, 475*0c036a14SPeter Spreadborough datalen, 476*0c036a14SPeter Spreadborough data); 477*0c036a14SPeter Spreadborough if (unlikely(!rc)) { 478*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "Failed to write blob\n"); 479*0c036a14SPeter Spreadborough return -EINVAL; 480*0c036a14SPeter Spreadborough } 481*0c036a14SPeter Spreadborough /* copy the previously stored data */ 482*0c036a14SPeter Spreadborough memcpy(&blob->data[ULP_BITS_2_BYTE_NR(offset + datalen)], local_data, 483*0c036a14SPeter Spreadborough ULP_BITS_2_BYTE(mov_len)); 484*0c036a14SPeter Spreadborough blob->write_idx += (mov_len + datalen); 485*0c036a14SPeter Spreadborough return 0; 486*0c036a14SPeter Spreadborough } 4877e604e7fSKishore Padmanabha 4887e604e7fSKishore Padmanabha /* 48988badb3aSMike Baucom * Add data to the binary blob at the current offset. 49088badb3aSMike Baucom * 49188badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 49288badb3aSMike Baucom * be initialized prior to pushing data. 49388badb3aSMike Baucom * 49488badb3aSMike Baucom * data [in] 64-bit value to be added to the blob. 49588badb3aSMike Baucom * 49688badb3aSMike Baucom * datalen [in] The number of bits to be added to the blob. 49788badb3aSMike Baucom * 49888badb3aSMike Baucom * The offset of the data is updated after each push of data. 499*0c036a14SPeter Spreadborough * NULL returned on error, pointer pushed value otherwise. 50088badb3aSMike Baucom */ 501*0c036a14SPeter Spreadborough static inline uint8_t * 50288badb3aSMike Baucom ulp_blob_push_64(struct ulp_blob *blob, 50388badb3aSMike Baucom uint64_t *data, 504*0c036a14SPeter Spreadborough uint32_t datalen) 505*0c036a14SPeter Spreadborough { 506*0c036a14SPeter Spreadborough uint8_t *val = (uint8_t *)data; 507*0c036a14SPeter Spreadborough int rc; 508*0c036a14SPeter Spreadborough 509*0c036a14SPeter Spreadborough int size = (datalen + 7) / 8; 510*0c036a14SPeter Spreadborough 511*0c036a14SPeter Spreadborough if (unlikely(!blob || !data || 512*0c036a14SPeter Spreadborough datalen > (uint32_t)(blob->bitlen - blob->write_idx))) { 513*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 514*0c036a14SPeter Spreadborough return NULL; 515*0c036a14SPeter Spreadborough } 516*0c036a14SPeter Spreadborough 517*0c036a14SPeter Spreadborough rc = ulp_blob_push(blob, &val[8 - size], datalen); 518*0c036a14SPeter Spreadborough if (unlikely(rc)) 519*0c036a14SPeter Spreadborough return NULL; 520*0c036a14SPeter Spreadborough 521*0c036a14SPeter Spreadborough return &val[8 - size]; 522*0c036a14SPeter Spreadborough } 52388badb3aSMike Baucom 52488badb3aSMike Baucom /* 525a2be13e1SKishore Padmanabha * Add data to the binary blob at the current offset. 526a2be13e1SKishore Padmanabha * 527a2be13e1SKishore Padmanabha * blob [in] The blob that data is added to. The blob must 528a2be13e1SKishore Padmanabha * be initialized prior to pushing data. 529a2be13e1SKishore Padmanabha * 530a2be13e1SKishore Padmanabha * data [in] 32-bit value to be added to the blob. 531a2be13e1SKishore Padmanabha * 532*0c036a14SPeter Spreadborough * datalen [in] The number of bits to be added to the blob. 533a2be13e1SKishore Padmanabha * 534a2be13e1SKishore Padmanabha * The offset of the data is updated after each push of data. 535a2be13e1SKishore Padmanabha * NULL returned on error, pointer pushed value otherwise. 536a2be13e1SKishore Padmanabha */ 537*0c036a14SPeter Spreadborough static inline uint8_t * 538a2be13e1SKishore Padmanabha ulp_blob_push_32(struct ulp_blob *blob, 539a2be13e1SKishore Padmanabha uint32_t *data, 540*0c036a14SPeter Spreadborough uint32_t datalen) 541*0c036a14SPeter Spreadborough { 542*0c036a14SPeter Spreadborough uint8_t *val = (uint8_t *)data; 543*0c036a14SPeter Spreadborough uint32_t rc; 544*0c036a14SPeter Spreadborough uint32_t size = ULP_BITS_2_BYTE(datalen); 545*0c036a14SPeter Spreadborough 546*0c036a14SPeter Spreadborough if (unlikely(!data || size > sizeof(uint32_t))) { 547*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 548*0c036a14SPeter Spreadborough return NULL; 549*0c036a14SPeter Spreadborough } 550*0c036a14SPeter Spreadborough 551*0c036a14SPeter Spreadborough rc = ulp_blob_push(blob, &val[sizeof(uint32_t) - size], datalen); 552*0c036a14SPeter Spreadborough if (unlikely(rc)) 553*0c036a14SPeter Spreadborough return NULL; 554*0c036a14SPeter Spreadborough 555*0c036a14SPeter Spreadborough return &val[sizeof(uint32_t) - size]; 556*0c036a14SPeter Spreadborough } 557a2be13e1SKishore Padmanabha 558a2be13e1SKishore Padmanabha /* 55988badb3aSMike Baucom * Add encap data to the binary blob at the current offset. 56088badb3aSMike Baucom * 56188badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 56288badb3aSMike Baucom * be initialized prior to pushing data. 56388badb3aSMike Baucom * 56488badb3aSMike Baucom * data [in] value to be added to the blob. 56588badb3aSMike Baucom * 56688badb3aSMike Baucom * datalen [in] The number of bits to be added to the blob. 56788badb3aSMike Baucom * 56888badb3aSMike Baucom * The offset of the data is updated after each push of data. 56988badb3aSMike Baucom * NULL returned on error, pointer pushed value otherwise. 57088badb3aSMike Baucom */ 571*0c036a14SPeter Spreadborough static inline int32_t 57288badb3aSMike Baucom ulp_blob_push_encap(struct ulp_blob *blob, 57388badb3aSMike Baucom uint8_t *data, 574*0c036a14SPeter Spreadborough uint32_t datalen) 575*0c036a14SPeter Spreadborough { 576*0c036a14SPeter Spreadborough uint8_t *val = (uint8_t *)data; 577*0c036a14SPeter Spreadborough uint32_t initial_size, write_size = datalen; 578*0c036a14SPeter Spreadborough uint32_t size = 0; 579*0c036a14SPeter Spreadborough 580*0c036a14SPeter Spreadborough if (unlikely(!blob || !data || 581*0c036a14SPeter Spreadborough datalen > (uint32_t)(blob->bitlen - blob->write_idx))) { 582*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 583*0c036a14SPeter Spreadborough return -1; 584*0c036a14SPeter Spreadborough } 585*0c036a14SPeter Spreadborough 586*0c036a14SPeter Spreadborough initial_size = ULP_BYTE_2_BITS(sizeof(uint64_t)) - 587*0c036a14SPeter Spreadborough (blob->write_idx % ULP_BYTE_2_BITS(sizeof(uint64_t))); 588*0c036a14SPeter Spreadborough while (write_size > 0) { 589*0c036a14SPeter Spreadborough if (initial_size && write_size > initial_size) { 590*0c036a14SPeter Spreadborough size = initial_size; 591*0c036a14SPeter Spreadborough initial_size = 0; 592*0c036a14SPeter Spreadborough } else if (initial_size && write_size <= initial_size) { 593*0c036a14SPeter Spreadborough size = write_size; 594*0c036a14SPeter Spreadborough initial_size = 0; 595*0c036a14SPeter Spreadborough } else if (write_size > ULP_BYTE_2_BITS(sizeof(uint64_t))) { 596*0c036a14SPeter Spreadborough size = ULP_BYTE_2_BITS(sizeof(uint64_t)); 597*0c036a14SPeter Spreadborough } else { 598*0c036a14SPeter Spreadborough size = write_size; 599*0c036a14SPeter Spreadborough } 600*0c036a14SPeter Spreadborough if (unlikely(ulp_blob_push(blob, val, size))) { 601*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "push field failed\n"); 602*0c036a14SPeter Spreadborough return -1; 603*0c036a14SPeter Spreadborough } 604*0c036a14SPeter Spreadborough val += ULP_BITS_2_BYTE(size); 605*0c036a14SPeter Spreadborough write_size -= size; 606*0c036a14SPeter Spreadborough } 607*0c036a14SPeter Spreadborough return datalen; 608*0c036a14SPeter Spreadborough } 60988badb3aSMike Baucom 61088badb3aSMike Baucom /* 611*0c036a14SPeter Spreadborough * Adds pad to an initialized blob at the current offset 61288badb3aSMike Baucom * 613*0c036a14SPeter Spreadborough * blob [in] The blob that data is added to. The blob must 614*0c036a14SPeter Spreadborough * be initialized prior to pushing data. 61588badb3aSMike Baucom * 616*0c036a14SPeter Spreadborough * datalen [in] The number of bits of pad to add 61788badb3aSMike Baucom * 618*0c036a14SPeter Spreadborough * returns the number of pad bits added, -1 on failure 61988badb3aSMike Baucom */ 620*0c036a14SPeter Spreadborough static inline int32_t 621*0c036a14SPeter Spreadborough ulp_blob_pad_push(struct ulp_blob *blob, 622*0c036a14SPeter Spreadborough uint32_t datalen) 623*0c036a14SPeter Spreadborough { 624*0c036a14SPeter Spreadborough if (unlikely(datalen > (uint32_t)(blob->bitlen - blob->write_idx))) { 625*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "Pad too large for blob\n"); 626*0c036a14SPeter Spreadborough return -1; 627*0c036a14SPeter Spreadborough } 628*0c036a14SPeter Spreadborough 629*0c036a14SPeter Spreadborough blob->write_idx += datalen; 630*0c036a14SPeter Spreadborough return datalen; 631*0c036a14SPeter Spreadborough } 63288badb3aSMike Baucom 63388badb3aSMike Baucom /* 634*0c036a14SPeter Spreadborough * Adds pad to an initialized blob at the current offset based on 635*0c036a14SPeter Spreadborough * the alignment. 6363fe124d2SKishore Padmanabha * 637*0c036a14SPeter Spreadborough * blob [in] The blob that needs to be aligned 6383fe124d2SKishore Padmanabha * 639*0c036a14SPeter Spreadborough * align [in] Alignment in bits. 640*0c036a14SPeter Spreadborough * 641*0c036a14SPeter Spreadborough * returns the number of pad bits added, -1 on failure 6423fe124d2SKishore Padmanabha */ 643*0c036a14SPeter Spreadborough static inline int32_t 644*0c036a14SPeter Spreadborough ulp_blob_pad_align(struct ulp_blob *blob, 645*0c036a14SPeter Spreadborough uint32_t align) 646*0c036a14SPeter Spreadborough { 647*0c036a14SPeter Spreadborough int32_t pad = 0; 648*0c036a14SPeter Spreadborough 649*0c036a14SPeter Spreadborough pad = RTE_ALIGN(blob->write_idx, align) - blob->write_idx; 650*0c036a14SPeter Spreadborough if (unlikely(pad > (int32_t)(blob->bitlen - blob->write_idx))) { 651*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "Pad too large for blob\n"); 652*0c036a14SPeter Spreadborough return -1; 653*0c036a14SPeter Spreadborough } 654*0c036a14SPeter Spreadborough blob->write_idx += pad; 655*0c036a14SPeter Spreadborough return pad; 656*0c036a14SPeter Spreadborough } 657*0c036a14SPeter Spreadborough 658*0c036a14SPeter Spreadborough /* Get data from src and put into dst using little-endian format */ 659*0c036a14SPeter Spreadborough static inline void 660*0c036a14SPeter Spreadborough ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst) 661*0c036a14SPeter Spreadborough { 662*0c036a14SPeter Spreadborough uint8_t bitoffs = bitpos % ULP_BLOB_BYTE; 663*0c036a14SPeter Spreadborough uint16_t index = ULP_BITS_2_BYTE_NR(bitpos); 664*0c036a14SPeter Spreadborough uint8_t mask, partial, shift; 665*0c036a14SPeter Spreadborough 666*0c036a14SPeter Spreadborough shift = bitoffs; 667*0c036a14SPeter Spreadborough partial = ULP_BLOB_BYTE - bitoffs; 668*0c036a14SPeter Spreadborough if (bitoffs + bitlen <= ULP_BLOB_BYTE) { 669*0c036a14SPeter Spreadborough mask = ((1 << bitlen) - 1) << shift; 670*0c036a14SPeter Spreadborough *dst = (src[index] & mask) >> shift; 671*0c036a14SPeter Spreadborough } else { 672*0c036a14SPeter Spreadborough mask = ((1 << partial) - 1) << shift; 673*0c036a14SPeter Spreadborough *dst = (src[index] & mask) >> shift; 674*0c036a14SPeter Spreadborough index++; 675*0c036a14SPeter Spreadborough partial = bitlen - partial; 676*0c036a14SPeter Spreadborough mask = ((1 << partial) - 1); 677*0c036a14SPeter Spreadborough *dst |= (src[index] & mask) << (ULP_BLOB_BYTE - bitoffs); 678*0c036a14SPeter Spreadborough } 679*0c036a14SPeter Spreadborough } 6803fe124d2SKishore Padmanabha 6813fe124d2SKishore Padmanabha /* 682f634204bSKishore Padmanabha * Get data from the byte array in Little endian format. 683f634204bSKishore Padmanabha * 684f634204bSKishore Padmanabha * src [in] The byte array where data is extracted from 685f634204bSKishore Padmanabha * 686f634204bSKishore Padmanabha * dst [out] The byte array where data is pulled into 687f634204bSKishore Padmanabha * 688f634204bSKishore Padmanabha * size [in] The size of dst array in bytes 689f634204bSKishore Padmanabha * 690f634204bSKishore Padmanabha * offset [in] The offset where data is pulled 691f634204bSKishore Padmanabha * 692f634204bSKishore Padmanabha * len [in] The number of bits to be extracted from the data array 693f634204bSKishore Padmanabha * 694f634204bSKishore Padmanabha * returns None. 695f634204bSKishore Padmanabha */ 696*0c036a14SPeter Spreadborough static inline void 697f634204bSKishore Padmanabha ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size, 698*0c036a14SPeter Spreadborough uint32_t offset, uint32_t len) 699*0c036a14SPeter Spreadborough { 700*0c036a14SPeter Spreadborough uint32_t idx; 701*0c036a14SPeter Spreadborough uint32_t cnt = ULP_BITS_2_BYTE_NR(len); 702*0c036a14SPeter Spreadborough 703*0c036a14SPeter Spreadborough /* iterate bytewise to get data */ 704*0c036a14SPeter Spreadborough for (idx = 0; idx < cnt; idx++) { 705*0c036a14SPeter Spreadborough ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE, 706*0c036a14SPeter Spreadborough &dst[size - 1 - idx]); 707*0c036a14SPeter Spreadborough offset += ULP_BLOB_BYTE; 708*0c036a14SPeter Spreadborough len -= ULP_BLOB_BYTE; 709*0c036a14SPeter Spreadborough } 710*0c036a14SPeter Spreadborough 711*0c036a14SPeter Spreadborough /* Extract the last reminder data that is not 8 byte boundary */ 712*0c036a14SPeter Spreadborough if (len) 713*0c036a14SPeter Spreadborough ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]); 714*0c036a14SPeter Spreadborough } 715*0c036a14SPeter Spreadborough 716*0c036a14SPeter Spreadborough /* 717*0c036a14SPeter Spreadborough * Get data from the byte array in Big endian format. 718*0c036a14SPeter Spreadborough * 719*0c036a14SPeter Spreadborough * src [in] The byte array where data is extracted from 720*0c036a14SPeter Spreadborough * 721*0c036a14SPeter Spreadborough * bitpos [in] The offset where data is pulled 722*0c036a14SPeter Spreadborough * 723*0c036a14SPeter Spreadborough * bitlen [in] The number of bits to be extracted from the data array 724*0c036a14SPeter Spreadborough * 725*0c036a14SPeter Spreadborough * dst [out] The byte array where data is pulled into 726*0c036a14SPeter Spreadborough * 727*0c036a14SPeter Spreadborough * returns None. 728*0c036a14SPeter Spreadborough */ 729*0c036a14SPeter Spreadborough /* Get data from src and put into dst using big-endian format */ 730*0c036a14SPeter Spreadborough static inline void 731*0c036a14SPeter Spreadborough ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst) 732*0c036a14SPeter Spreadborough { 733*0c036a14SPeter Spreadborough uint8_t bitoffs = bitpos % ULP_BLOB_BYTE; 734*0c036a14SPeter Spreadborough uint16_t index = ULP_BITS_2_BYTE_NR(bitpos); 735*0c036a14SPeter Spreadborough uint8_t mask; 736*0c036a14SPeter Spreadborough int32_t shift; 737*0c036a14SPeter Spreadborough 738*0c036a14SPeter Spreadborough shift = ULP_BLOB_BYTE - bitoffs - bitlen; 739*0c036a14SPeter Spreadborough if (shift >= 0) { 740*0c036a14SPeter Spreadborough mask = 0xFF >> -bitlen; 741*0c036a14SPeter Spreadborough *dst = (src[index] >> shift) & mask; 742*0c036a14SPeter Spreadborough } else { 743*0c036a14SPeter Spreadborough *dst = (src[index] & (0xFF >> bitoffs)) << -shift; 744*0c036a14SPeter Spreadborough *dst |= src[index + 1] >> -shift; 745*0c036a14SPeter Spreadborough } 746*0c036a14SPeter Spreadborough } 747f634204bSKishore Padmanabha 748f634204bSKishore Padmanabha /* 749f634204bSKishore Padmanabha * Get data from the byte array in Big endian format. 750f634204bSKishore Padmanabha * 751f634204bSKishore Padmanabha * src [in] The byte array where data is extracted from 752f634204bSKishore Padmanabha * 753f634204bSKishore Padmanabha * dst [out] The byte array where data is pulled into 754f634204bSKishore Padmanabha * 755f634204bSKishore Padmanabha * offset [in] The offset where data is pulled 756f634204bSKishore Padmanabha * 757f634204bSKishore Padmanabha * len [in] The number of bits to be extracted from the data array 758f634204bSKishore Padmanabha * 759f634204bSKishore Padmanabha * returns None. 760f634204bSKishore Padmanabha */ 761*0c036a14SPeter Spreadborough static inline void 762f634204bSKishore Padmanabha ulp_bs_pull_msb(uint8_t *src, uint8_t *dst, 763*0c036a14SPeter Spreadborough uint32_t offset, uint32_t len) 764*0c036a14SPeter Spreadborough { 765*0c036a14SPeter Spreadborough uint32_t idx; 766*0c036a14SPeter Spreadborough uint32_t cnt = ULP_BITS_2_BYTE_NR(len); 767*0c036a14SPeter Spreadborough 768*0c036a14SPeter Spreadborough /* iterate bytewise to get data */ 769*0c036a14SPeter Spreadborough for (idx = 0; idx < cnt; idx++) { 770*0c036a14SPeter Spreadborough ulp_bs_get_msb(src, offset, ULP_BLOB_BYTE, &dst[idx]); 771*0c036a14SPeter Spreadborough offset += ULP_BLOB_BYTE; 772*0c036a14SPeter Spreadborough len -= ULP_BLOB_BYTE; 773*0c036a14SPeter Spreadborough } 774*0c036a14SPeter Spreadborough 775*0c036a14SPeter Spreadborough /* Extract the last reminder data that is not 8 byte boundary */ 776*0c036a14SPeter Spreadborough if (len) 777*0c036a14SPeter Spreadborough ulp_bs_get_msb(src, offset, len, &dst[idx]); 778*0c036a14SPeter Spreadborough } 779f634204bSKishore Padmanabha 780f634204bSKishore Padmanabha /* 781afd35335SKishore Padmanabha * Extract data from the binary blob using given offset. 782afd35335SKishore Padmanabha * 783afd35335SKishore Padmanabha * blob [in] The blob that data is extracted from. The blob must 784afd35335SKishore Padmanabha * be initialized prior to pulling data. 785afd35335SKishore Padmanabha * 786afd35335SKishore Padmanabha * data [in] A pointer to put the data. 787afd35335SKishore Padmanabha * data_size [in] size of the data buffer in bytes. 788afd35335SKishore Padmanabha *offset [in] - Offset in the blob to extract the data in bits format. 789afd35335SKishore Padmanabha * len [in] The number of bits to be pulled from the blob. 790afd35335SKishore Padmanabha * 791afd35335SKishore Padmanabha * Output: zero on success, -1 on failure 792afd35335SKishore Padmanabha */ 793*0c036a14SPeter Spreadborough static inline int32_t 794afd35335SKishore Padmanabha ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size, 795*0c036a14SPeter Spreadborough uint16_t offset, uint16_t len) 796*0c036a14SPeter Spreadborough { 797*0c036a14SPeter Spreadborough /* validate the arguments */ 798*0c036a14SPeter Spreadborough if (unlikely(!blob || (offset + len) > blob->bitlen || 799*0c036a14SPeter Spreadborough ULP_BYTE_2_BITS(data_size) < len)) { 800*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 801*0c036a14SPeter Spreadborough return -1; /* failure */ 802*0c036a14SPeter Spreadborough } 803*0c036a14SPeter Spreadborough 804*0c036a14SPeter Spreadborough if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) 805*0c036a14SPeter Spreadborough ulp_bs_pull_msb(blob->data, data, offset, len); 806*0c036a14SPeter Spreadborough else 807*0c036a14SPeter Spreadborough ulp_bs_pull_lsb(blob->data, data, data_size, offset, len); 808*0c036a14SPeter Spreadborough return 0; 809*0c036a14SPeter Spreadborough } 810afd35335SKishore Padmanabha 811afd35335SKishore Padmanabha /* 812*0c036a14SPeter Spreadborough * Get the data portion of the binary blob. 81388badb3aSMike Baucom * 814*0c036a14SPeter Spreadborough * blob [in] The blob's data to be retrieved. The blob must be 815*0c036a14SPeter Spreadborough * initialized prior to pushing data. 81688badb3aSMike Baucom * 817*0c036a14SPeter Spreadborough * datalen [out] The number of bits that are filled. 81888badb3aSMike Baucom * 819*0c036a14SPeter Spreadborough * Returns a byte array of the blob data or NULL on error. 82088badb3aSMike Baucom */ 821*0c036a14SPeter Spreadborough static inline uint8_t * 822*0c036a14SPeter Spreadborough ulp_blob_data_get(struct ulp_blob *blob, 823*0c036a14SPeter Spreadborough uint16_t *datalen) 824*0c036a14SPeter Spreadborough { 825*0c036a14SPeter Spreadborough /* validate the arguments */ 826*0c036a14SPeter Spreadborough if (unlikely(!blob)) { 827*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 828*0c036a14SPeter Spreadborough return NULL; /* failure */ 829*0c036a14SPeter Spreadborough } 830*0c036a14SPeter Spreadborough *datalen = blob->write_idx; 831*0c036a14SPeter Spreadborough return blob->data; 832*0c036a14SPeter Spreadborough } 83388badb3aSMike Baucom 83488badb3aSMike Baucom /* 835*0c036a14SPeter Spreadborough * Get the data length of the binary blob. 8363fe124d2SKishore Padmanabha * 837*0c036a14SPeter Spreadborough * blob [in] The blob's data len to be retrieved. 8383fe124d2SKishore Padmanabha * 839*0c036a14SPeter Spreadborough * returns length of the binary blob 8403fe124d2SKishore Padmanabha */ 841*0c036a14SPeter Spreadborough static inline uint16_t 842*0c036a14SPeter Spreadborough ulp_blob_data_len_get(struct ulp_blob *blob) 843*0c036a14SPeter Spreadborough { 844*0c036a14SPeter Spreadborough /* validate the arguments */ 845*0c036a14SPeter Spreadborough if (unlikely(!blob)) { 846*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 847*0c036a14SPeter Spreadborough return 0; /* failure */ 848*0c036a14SPeter Spreadborough } 849*0c036a14SPeter Spreadborough return blob->write_idx; 850*0c036a14SPeter Spreadborough } 8513fe124d2SKishore Padmanabha 8523fe124d2SKishore Padmanabha /* 853*0c036a14SPeter Spreadborough * Set the encap swap start index of the binary blob. 85488badb3aSMike Baucom * 85588badb3aSMike Baucom * blob [in] The blob's data to be retrieved. The blob must be 85688badb3aSMike Baucom * initialized prior to pushing data. 85788badb3aSMike Baucom * 85888badb3aSMike Baucom * returns void. 85988badb3aSMike Baucom */ 860*0c036a14SPeter Spreadborough static inline void 861*0c036a14SPeter Spreadborough ulp_blob_encap_swap_idx_set(struct ulp_blob *blob) 862*0c036a14SPeter Spreadborough { 863*0c036a14SPeter Spreadborough /* validate the arguments */ 864*0c036a14SPeter Spreadborough if (unlikely(!blob)) { 865*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 866*0c036a14SPeter Spreadborough return; /* failure */ 867*0c036a14SPeter Spreadborough } 868*0c036a14SPeter Spreadborough blob->encap_swap_idx = blob->write_idx; 869*0c036a14SPeter Spreadborough } 87088badb3aSMike Baucom 87188badb3aSMike Baucom /* 87288badb3aSMike Baucom * Perform the encap buffer swap to 64 bit reversal. 87388badb3aSMike Baucom * 87488badb3aSMike Baucom * blob [in] The blob's data to be used for swap. 87588badb3aSMike Baucom * 87688badb3aSMike Baucom * returns void. 87788badb3aSMike Baucom */ 878*0c036a14SPeter Spreadborough static inline void 879*0c036a14SPeter Spreadborough ulp_blob_perform_encap_swap(struct ulp_blob *blob) 880*0c036a14SPeter Spreadborough { 881*0c036a14SPeter Spreadborough uint32_t i, idx = 0, end_idx = 0, roundoff; 882*0c036a14SPeter Spreadborough uint8_t temp_val_1, temp_val_2; 883*0c036a14SPeter Spreadborough 884*0c036a14SPeter Spreadborough /* validate the arguments */ 885*0c036a14SPeter Spreadborough if (unlikely(!blob)) { 886*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 887*0c036a14SPeter Spreadborough return; /* failure */ 888*0c036a14SPeter Spreadborough } 889*0c036a14SPeter Spreadborough idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx); 890*0c036a14SPeter Spreadborough end_idx = ULP_BITS_2_BYTE(blob->write_idx); 891*0c036a14SPeter Spreadborough roundoff = ULP_BYTE_2_BITS(ULP_BITS_2_BYTE(end_idx)); 892*0c036a14SPeter Spreadborough if (roundoff > end_idx) { 893*0c036a14SPeter Spreadborough blob->write_idx += ULP_BYTE_2_BITS(roundoff - end_idx); 894*0c036a14SPeter Spreadborough end_idx = roundoff; 895*0c036a14SPeter Spreadborough } 896*0c036a14SPeter Spreadborough while (idx <= end_idx) { 897*0c036a14SPeter Spreadborough for (i = 0; i < 4; i = i + 2) { 898*0c036a14SPeter Spreadborough temp_val_1 = blob->data[idx + i]; 899*0c036a14SPeter Spreadborough temp_val_2 = blob->data[idx + i + 1]; 900*0c036a14SPeter Spreadborough blob->data[idx + i] = blob->data[idx + 6 - i]; 901*0c036a14SPeter Spreadborough blob->data[idx + i + 1] = blob->data[idx + 7 - i]; 902*0c036a14SPeter Spreadborough blob->data[idx + 7 - i] = temp_val_2; 903*0c036a14SPeter Spreadborough blob->data[idx + 6 - i] = temp_val_1; 904*0c036a14SPeter Spreadborough } 905*0c036a14SPeter Spreadborough idx += 8; 906*0c036a14SPeter Spreadborough } 907*0c036a14SPeter Spreadborough } 90888badb3aSMike Baucom 90988badb3aSMike Baucom /* 910a4651725SMike Baucom * Perform the blob buffer reversal byte wise. 911a4651725SMike Baucom * This api makes the first byte the last and 912a4651725SMike Baucom * vice-versa. 913a4651725SMike Baucom * 914a4651725SMike Baucom * blob [in] The blob's data to be used for swap. 9153fe124d2SKishore Padmanabha * chunk_size[in] the swap is done within the chunk in bytes 916a4651725SMike Baucom * 917a4651725SMike Baucom * returns void. 918a4651725SMike Baucom */ 919*0c036a14SPeter Spreadborough static inline void 9203fe124d2SKishore Padmanabha ulp_blob_perform_byte_reverse(struct ulp_blob *blob, 921*0c036a14SPeter Spreadborough uint32_t chunk_size) 922*0c036a14SPeter Spreadborough { 923*0c036a14SPeter Spreadborough uint32_t idx = 0, jdx = 0, num = 0; 924*0c036a14SPeter Spreadborough uint8_t xchar; 925*0c036a14SPeter Spreadborough uint8_t *buff; 926*0c036a14SPeter Spreadborough 927*0c036a14SPeter Spreadborough /* validate the arguments */ 928*0c036a14SPeter Spreadborough if (unlikely(!blob)) { 929*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 930*0c036a14SPeter Spreadborough return; /* failure */ 931*0c036a14SPeter Spreadborough } 932*0c036a14SPeter Spreadborough 933*0c036a14SPeter Spreadborough buff = blob->data; 934*0c036a14SPeter Spreadborough num = ULP_BITS_2_BYTE(blob->write_idx) / chunk_size; 935*0c036a14SPeter Spreadborough for (idx = 0; idx < num; idx++) { 936*0c036a14SPeter Spreadborough for (jdx = 0; jdx < chunk_size / 2; jdx++) { 937*0c036a14SPeter Spreadborough xchar = buff[jdx]; 938*0c036a14SPeter Spreadborough buff[jdx] = buff[(chunk_size - 1) - jdx]; 939*0c036a14SPeter Spreadborough buff[(chunk_size - 1) - jdx] = xchar; 940*0c036a14SPeter Spreadborough } 941*0c036a14SPeter Spreadborough buff += chunk_size; 942*0c036a14SPeter Spreadborough } 943*0c036a14SPeter Spreadborough } 944a4651725SMike Baucom 945a4651725SMike Baucom /* 9467e604e7fSKishore Padmanabha * Perform the blob buffer 64 bit word swap. 9477e604e7fSKishore Padmanabha * This api makes the first 4 bytes the last in 9487e604e7fSKishore Padmanabha * a given 64 bit value and vice-versa. 9497e604e7fSKishore Padmanabha * 9507e604e7fSKishore Padmanabha * blob [in] The blob's data to be used for swap. 9517e604e7fSKishore Padmanabha * 9527e604e7fSKishore Padmanabha * returns void. 9537e604e7fSKishore Padmanabha */ 954*0c036a14SPeter Spreadborough static inline void 955*0c036a14SPeter Spreadborough ulp_blob_perform_64B_word_swap(struct ulp_blob *blob) 956*0c036a14SPeter Spreadborough { 957*0c036a14SPeter Spreadborough uint32_t i, j, num; 958*0c036a14SPeter Spreadborough uint8_t xchar; 959*0c036a14SPeter Spreadborough uint32_t word_size = ULP_64B_IN_BYTES / 2; 960*0c036a14SPeter Spreadborough 961*0c036a14SPeter Spreadborough /* validate the arguments */ 962*0c036a14SPeter Spreadborough if (unlikely(!blob)) { 963*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 964*0c036a14SPeter Spreadborough return; /* failure */ 965*0c036a14SPeter Spreadborough } 966*0c036a14SPeter Spreadborough num = ULP_BITS_2_BYTE(blob->write_idx); 967*0c036a14SPeter Spreadborough for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) { 968*0c036a14SPeter Spreadborough for (j = 0; j < word_size; j++) { 969*0c036a14SPeter Spreadborough xchar = blob->data[i + j]; 970*0c036a14SPeter Spreadborough blob->data[i + j] = blob->data[i + j + word_size]; 971*0c036a14SPeter Spreadborough blob->data[i + j + word_size] = xchar; 972*0c036a14SPeter Spreadborough } 973*0c036a14SPeter Spreadborough } 974*0c036a14SPeter Spreadborough } 9757e604e7fSKishore Padmanabha 9767e604e7fSKishore Padmanabha /* 9777e604e7fSKishore Padmanabha * Perform the blob buffer 64 bit byte swap. 9787e604e7fSKishore Padmanabha * This api makes the first byte the last in 9797e604e7fSKishore Padmanabha * a given 64 bit value and vice-versa. 9807e604e7fSKishore Padmanabha * 9817e604e7fSKishore Padmanabha * blob [in] The blob's data to be used for swap. 9827e604e7fSKishore Padmanabha * 9837e604e7fSKishore Padmanabha * returns void. 9847e604e7fSKishore Padmanabha */ 985*0c036a14SPeter Spreadborough static inline void 986*0c036a14SPeter Spreadborough ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob) 987*0c036a14SPeter Spreadborough { 988*0c036a14SPeter Spreadborough uint32_t i, j, num; 989*0c036a14SPeter Spreadborough uint8_t xchar; 990*0c036a14SPeter Spreadborough uint32_t offset = ULP_64B_IN_BYTES - 1; 991*0c036a14SPeter Spreadborough 992*0c036a14SPeter Spreadborough /* validate the arguments */ 993*0c036a14SPeter Spreadborough if (unlikely(!blob)) { 994*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 995*0c036a14SPeter Spreadborough return; /* failure */ 996*0c036a14SPeter Spreadborough } 997*0c036a14SPeter Spreadborough num = ULP_BITS_2_BYTE(blob->write_idx); 998*0c036a14SPeter Spreadborough for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) { 999*0c036a14SPeter Spreadborough for (j = 0; j < (ULP_64B_IN_BYTES / 2); j++) { 1000*0c036a14SPeter Spreadborough xchar = blob->data[i + j]; 1001*0c036a14SPeter Spreadborough blob->data[i + j] = blob->data[i + offset - j]; 1002*0c036a14SPeter Spreadborough blob->data[i + offset - j] = xchar; 1003*0c036a14SPeter Spreadborough } 1004*0c036a14SPeter Spreadborough } 1005*0c036a14SPeter Spreadborough } 10067e604e7fSKishore Padmanabha 10077e604e7fSKishore Padmanabha /* 10083fe124d2SKishore Padmanabha * Perform the blob buffer merge. 10093fe124d2SKishore Padmanabha * This api makes the src blob merged to the dst blob. 10103fe124d2SKishore Padmanabha * The block size and pad size help in padding the dst blob 10113fe124d2SKishore Padmanabha * 10123fe124d2SKishore Padmanabha * dst [in] The destination blob, the blob to be merged. 10133fe124d2SKishore Padmanabha * src [in] The src blob. 1014*0c036a14SPeter Spreadborough * block_size [in] The size of the block in bytes after which padding gets 1015*0c036a14SPeter Spreadborough * applied. 10163fe124d2SKishore Padmanabha * pad [in] The size of the pad to be applied. 10173fe124d2SKishore Padmanabha * 10183fe124d2SKishore Padmanabha * returns 0 on success. 10193fe124d2SKishore Padmanabha */ 1020*0c036a14SPeter Spreadborough static inline int32_t 1021*0c036a14SPeter Spreadborough ulp_blob_msb_block_merge(struct ulp_blob *dst, struct ulp_blob *src, 1022*0c036a14SPeter Spreadborough uint32_t block_size, uint32_t pad) 1023*0c036a14SPeter Spreadborough { 1024*0c036a14SPeter Spreadborough uint32_t i, k, write_bytes, remaining; 1025*0c036a14SPeter Spreadborough uint16_t num; 1026*0c036a14SPeter Spreadborough uint8_t *src_buf = ulp_blob_data_get(src, &num); 1027*0c036a14SPeter Spreadborough uint8_t bluff; 1028*0c036a14SPeter Spreadborough 1029*0c036a14SPeter Spreadborough for (i = 0; i < num;) { 1030*0c036a14SPeter Spreadborough if (((dst->write_idx % block_size) + (num - i)) > block_size) 1031*0c036a14SPeter Spreadborough write_bytes = block_size - 1032*0c036a14SPeter Spreadborough (dst->write_idx % block_size); 1033*0c036a14SPeter Spreadborough else 1034*0c036a14SPeter Spreadborough write_bytes = num - i; 1035*0c036a14SPeter Spreadborough for (k = 0; k < ULP_BITS_2_BYTE_NR(write_bytes); k++) { 1036*0c036a14SPeter Spreadborough ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE, 1037*0c036a14SPeter Spreadborough *src_buf); 1038*0c036a14SPeter Spreadborough dst->write_idx += ULP_BLOB_BYTE; 1039*0c036a14SPeter Spreadborough src_buf++; 1040*0c036a14SPeter Spreadborough } 1041*0c036a14SPeter Spreadborough remaining = write_bytes % ULP_BLOB_BYTE; 1042*0c036a14SPeter Spreadborough if (remaining) { 1043*0c036a14SPeter Spreadborough bluff = (*src_buf) & ((uint8_t)-1 << 1044*0c036a14SPeter Spreadborough (ULP_BLOB_BYTE - remaining)); 1045*0c036a14SPeter Spreadborough ulp_bs_put_msb(dst->data, dst->write_idx, 1046*0c036a14SPeter Spreadborough ULP_BLOB_BYTE, bluff); 1047*0c036a14SPeter Spreadborough dst->write_idx += remaining; 1048*0c036a14SPeter Spreadborough } 1049*0c036a14SPeter Spreadborough if (write_bytes != (num - i)) { 1050*0c036a14SPeter Spreadborough /* add the padding */ 1051*0c036a14SPeter Spreadborough ulp_blob_pad_push(dst, pad); 1052*0c036a14SPeter Spreadborough if (remaining) { 1053*0c036a14SPeter Spreadborough ulp_bs_put_msb(dst->data, dst->write_idx, 1054*0c036a14SPeter Spreadborough ULP_BLOB_BYTE - remaining, 1055*0c036a14SPeter Spreadborough *src_buf); 1056*0c036a14SPeter Spreadborough dst->write_idx += ULP_BLOB_BYTE - remaining; 1057*0c036a14SPeter Spreadborough src_buf++; 1058*0c036a14SPeter Spreadborough } 1059*0c036a14SPeter Spreadborough } 1060*0c036a14SPeter Spreadborough i += write_bytes; 1061*0c036a14SPeter Spreadborough } 1062*0c036a14SPeter Spreadborough return 0; 1063*0c036a14SPeter Spreadborough } 10643fe124d2SKishore Padmanabha 10653fe124d2SKishore Padmanabha /* 1066*0c036a14SPeter Spreadborough * Perform the blob buffer merge. 1067*0c036a14SPeter Spreadborough * This api makes the src blob merged to the dst blob. 1068*0c036a14SPeter Spreadborough * The block size and pad size help in padding the dst blob 10693fe124d2SKishore Padmanabha * 1070*0c036a14SPeter Spreadborough * dst [in] The destination blob, the blob to be merged. 1071*0c036a14SPeter Spreadborough * src [in] The src blob. 1072*0c036a14SPeter Spreadborough * block_size [in] The size of the block in bytes after which padding gets 1073*0c036a14SPeter Spreadborough * applied. 1074*0c036a14SPeter Spreadborough * pad [in] The size of the pad to be applied. 10753fe124d2SKishore Padmanabha * 1076*0c036a14SPeter Spreadborough * returns 0 on success. 10773fe124d2SKishore Padmanabha */ 1078*0c036a14SPeter Spreadborough static inline int32_t 1079*0c036a14SPeter Spreadborough ulp_blob_block_merge(struct ulp_blob *dst, struct ulp_blob *src, 1080*0c036a14SPeter Spreadborough uint32_t block_size, uint32_t pad) 1081*0c036a14SPeter Spreadborough { 1082*0c036a14SPeter Spreadborough if (dst->byte_order == BNXT_ULP_BYTE_ORDER_BE && 1083*0c036a14SPeter Spreadborough src->byte_order == BNXT_ULP_BYTE_ORDER_BE) 1084*0c036a14SPeter Spreadborough return ulp_blob_msb_block_merge(dst, src, block_size, pad); 1085*0c036a14SPeter Spreadborough 1086*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "block merge not implemented yet\n"); 1087*0c036a14SPeter Spreadborough return -EINVAL; 1088*0c036a14SPeter Spreadborough } 1089*0c036a14SPeter Spreadborough 1090*0c036a14SPeter Spreadborough /* 1091*0c036a14SPeter Spreadborough * Perform the blob buffer append. 1092*0c036a14SPeter Spreadborough * 1093*0c036a14SPeter Spreadborough * dst [in] The destination blob, the blob to be merged. 1094*0c036a14SPeter Spreadborough * src [in] The src blob. 1095*0c036a14SPeter Spreadborough * src_offset [in] Offset of src data. 1096*0c036a14SPeter Spreadborough * src_len [in] The size of the src data. 1097*0c036a14SPeter Spreadborough * 1098*0c036a14SPeter Spreadborough * returns 0 on success. 1099*0c036a14SPeter Spreadborough */ 1100*0c036a14SPeter Spreadborough static inline int32_t 11013fe124d2SKishore Padmanabha ulp_blob_append(struct ulp_blob *dst, struct ulp_blob *src, 1102*0c036a14SPeter Spreadborough uint16_t src_offset, uint16_t src_len) 1103*0c036a14SPeter Spreadborough { 1104*0c036a14SPeter Spreadborough uint32_t k, remaining = 0; 1105*0c036a14SPeter Spreadborough uint16_t num; 1106*0c036a14SPeter Spreadborough uint8_t bluff; 1107*0c036a14SPeter Spreadborough uint8_t *src_buf = ulp_blob_data_get(src, &num); 1108*0c036a14SPeter Spreadborough 1109*0c036a14SPeter Spreadborough if (unlikely((src_offset + src_len) > num)) 1110*0c036a14SPeter Spreadborough return -EINVAL; 1111*0c036a14SPeter Spreadborough 1112*0c036a14SPeter Spreadborough /* Only supporting BE for now */ 1113*0c036a14SPeter Spreadborough if (unlikely(src->byte_order != BNXT_ULP_BYTE_ORDER_BE || 1114*0c036a14SPeter Spreadborough dst->byte_order != BNXT_ULP_BYTE_ORDER_BE)) 1115*0c036a14SPeter Spreadborough return -EINVAL; 1116*0c036a14SPeter Spreadborough 1117*0c036a14SPeter Spreadborough /* Handle if the source offset is not on a byte boundary */ 1118*0c036a14SPeter Spreadborough remaining = src_offset % ULP_BLOB_BYTE; 1119*0c036a14SPeter Spreadborough if (remaining) { 1120*0c036a14SPeter Spreadborough bluff = src_buf[src_offset / ULP_BLOB_BYTE] & ((uint8_t)-1 >> 1121*0c036a14SPeter Spreadborough (ULP_BLOB_BYTE - remaining)); 1122*0c036a14SPeter Spreadborough ulp_bs_put_msb(dst->data, dst->write_idx, remaining, bluff); 1123*0c036a14SPeter Spreadborough dst->write_idx += remaining; 1124*0c036a14SPeter Spreadborough src_offset += remaining; 1125*0c036a14SPeter Spreadborough } 1126*0c036a14SPeter Spreadborough 1127*0c036a14SPeter Spreadborough src_buf += ULP_BITS_2_BYTE_NR(src_offset); 1128*0c036a14SPeter Spreadborough 1129*0c036a14SPeter Spreadborough /* Push the byte aligned pieces */ 1130*0c036a14SPeter Spreadborough for (k = 0; k < ULP_BITS_2_BYTE_NR(src_len); k++) { 1131*0c036a14SPeter Spreadborough ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE, 1132*0c036a14SPeter Spreadborough *src_buf); 1133*0c036a14SPeter Spreadborough dst->write_idx += ULP_BLOB_BYTE; 1134*0c036a14SPeter Spreadborough src_buf++; 1135*0c036a14SPeter Spreadborough } 1136*0c036a14SPeter Spreadborough 1137*0c036a14SPeter Spreadborough /* Handle the remaining if length is not a byte boundary */ 1138*0c036a14SPeter Spreadborough if (src_len > remaining) 1139*0c036a14SPeter Spreadborough remaining = (src_len - remaining) % ULP_BLOB_BYTE; 1140*0c036a14SPeter Spreadborough else 1141*0c036a14SPeter Spreadborough remaining = 0; 1142*0c036a14SPeter Spreadborough if (remaining) { 1143*0c036a14SPeter Spreadborough bluff = (*src_buf) & ((uint8_t)-1 << 1144*0c036a14SPeter Spreadborough (ULP_BLOB_BYTE - remaining)); 1145*0c036a14SPeter Spreadborough ulp_bs_put_msb(dst->data, dst->write_idx, 1146*0c036a14SPeter Spreadborough ULP_BLOB_BYTE, bluff); 1147*0c036a14SPeter Spreadborough dst->write_idx += remaining; 1148*0c036a14SPeter Spreadborough } 1149*0c036a14SPeter Spreadborough 1150*0c036a14SPeter Spreadborough return 0; 1151*0c036a14SPeter Spreadborough } 11523fe124d2SKishore Padmanabha 11533fe124d2SKishore Padmanabha /* 1154f63aa27dSKishore Padmanabha * Perform the blob buffer copy. 1155f63aa27dSKishore Padmanabha * This api makes the src blob merged to the dst blob. 1156f63aa27dSKishore Padmanabha * 1157f63aa27dSKishore Padmanabha * dst [in] The destination blob, the blob to be merged. 1158f63aa27dSKishore Padmanabha * src [in] The src blob. 1159f63aa27dSKishore Padmanabha * 1160f63aa27dSKishore Padmanabha * returns 0 on success. 1161f63aa27dSKishore Padmanabha */ 1162*0c036a14SPeter Spreadborough static inline int32_t 1163*0c036a14SPeter Spreadborough ulp_blob_buffer_copy(struct ulp_blob *dst, struct ulp_blob *src) 1164*0c036a14SPeter Spreadborough { 1165*0c036a14SPeter Spreadborough if (unlikely((dst->write_idx + src->write_idx) > dst->bitlen)) { 1166*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "source buffer too large\n"); 1167*0c036a14SPeter Spreadborough return -EINVAL; 1168*0c036a14SPeter Spreadborough } 1169*0c036a14SPeter Spreadborough if (unlikely(ULP_BITS_IS_BYTE_NOT_ALIGNED(dst->write_idx) || 1170*0c036a14SPeter Spreadborough ULP_BITS_IS_BYTE_NOT_ALIGNED(src->write_idx))) { 1171*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "source buffer is not aligned\n"); 1172*0c036a14SPeter Spreadborough return -EINVAL; 1173*0c036a14SPeter Spreadborough } 1174*0c036a14SPeter Spreadborough memcpy(&dst->data[ULP_BITS_2_BYTE_NR(dst->write_idx)], 1175*0c036a14SPeter Spreadborough src->data, ULP_BITS_2_BYTE_NR(src->write_idx)); 1176*0c036a14SPeter Spreadborough dst->write_idx += src->write_idx; 1177*0c036a14SPeter Spreadborough return 0; 1178*0c036a14SPeter Spreadborough } 1179f63aa27dSKishore Padmanabha 1180f63aa27dSKishore Padmanabha /* 118188badb3aSMike Baucom * Read data from the operand 118288badb3aSMike Baucom * 118388badb3aSMike Baucom * operand [in] A pointer to a 16 Byte operand 118488badb3aSMike Baucom * 118588badb3aSMike Baucom * val [in/out] The variable to copy the operand to 118688badb3aSMike Baucom * 1187*0c036a14SPeter Spreadborough * bytes [in] The number of bytes to read into val 118888badb3aSMike Baucom * 1189c569279aSShuanglin Wang * returns zero on success. 119088badb3aSMike Baucom */ 1191*0c036a14SPeter Spreadborough static inline int32_t 119288badb3aSMike Baucom ulp_operand_read(uint8_t *operand, 119388badb3aSMike Baucom uint8_t *val, 1194*0c036a14SPeter Spreadborough uint16_t bytes) 1195*0c036a14SPeter Spreadborough { 1196*0c036a14SPeter Spreadborough /* validate the arguments */ 1197*0c036a14SPeter Spreadborough if (unlikely(!operand || !val)) { 1198*0c036a14SPeter Spreadborough BNXT_DRV_DBG(ERR, "invalid argument\n"); 1199*0c036a14SPeter Spreadborough return -EINVAL; 1200*0c036a14SPeter Spreadborough } 1201*0c036a14SPeter Spreadborough memcpy(val, operand, bytes); 1202*0c036a14SPeter Spreadborough return 0; 1203*0c036a14SPeter Spreadborough } 12042bbcdee8SKishore Padmanabha 12052bbcdee8SKishore Padmanabha /* Function to check if bitmap is ones. Return 1 on success */ 1206*0c036a14SPeter Spreadborough static inline uint32_t 1207*0c036a14SPeter Spreadborough ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size) 1208*0c036a14SPeter Spreadborough { 1209*0c036a14SPeter Spreadborough while (size-- > 0) { 1210*0c036a14SPeter Spreadborough if (*bitmap != 0xFF) 1211*0c036a14SPeter Spreadborough return 0; 1212*0c036a14SPeter Spreadborough bitmap++; 1213*0c036a14SPeter Spreadborough } 1214*0c036a14SPeter Spreadborough return 1; 1215*0c036a14SPeter Spreadborough } 12162bbcdee8SKishore Padmanabha 12172bbcdee8SKishore Padmanabha /* Function to check if bitmap is not zero. Return 1 on success */ 1218*0c036a14SPeter Spreadborough static inline uint32_t 1219*0c036a14SPeter Spreadborough ulp_bitmap_notzero(const uint8_t *bitmap, int32_t size) 1220*0c036a14SPeter Spreadborough { 1221*0c036a14SPeter Spreadborough while (size-- > 0) { 1222*0c036a14SPeter Spreadborough if (*bitmap != 0) 1223*0c036a14SPeter Spreadborough return 1; 1224*0c036a14SPeter Spreadborough bitmap++; 1225*0c036a14SPeter Spreadborough } 1226*0c036a14SPeter Spreadborough return 0; 1227*0c036a14SPeter Spreadborough } 12282bbcdee8SKishore Padmanabha 12290001cc58SKishore Padmanabha /* returns 0 if input is power of 2 */ 1230*0c036a14SPeter Spreadborough static inline int32_t 1231*0c036a14SPeter Spreadborough ulp_util_is_power_of_2(uint64_t x) 1232*0c036a14SPeter Spreadborough { 1233*0c036a14SPeter Spreadborough if (((x - 1) & x)) 1234*0c036a14SPeter Spreadborough return -1; 1235*0c036a14SPeter Spreadborough return 0; 1236*0c036a14SPeter Spreadborough } 123788badb3aSMike Baucom #endif /* _ULP_UTILS_H_ */ 1238