188badb3aSMike Baucom /* SPDX-License-Identifier: BSD-3-Clause 22addc463SAjit Khaparde * Copyright(c) 2014-2021 Broadcom 388badb3aSMike Baucom * All rights reserved. 488badb3aSMike Baucom */ 588badb3aSMike Baucom 688badb3aSMike Baucom #include "ulp_utils.h" 788badb3aSMike Baucom #include "bnxt_tf_common.h" 888badb3aSMike Baucom 988badb3aSMike Baucom /* 1088badb3aSMike Baucom * Initialize the regfile structure for writing 1188badb3aSMike Baucom * 1288badb3aSMike Baucom * regfile [in] Ptr to a regfile instance 1388badb3aSMike Baucom * 1488badb3aSMike Baucom * returns 0 on error or 1 on success 1588badb3aSMike Baucom */ 1688badb3aSMike Baucom uint32_t 1788badb3aSMike Baucom ulp_regfile_init(struct ulp_regfile *regfile) 1888badb3aSMike Baucom { 1988badb3aSMike Baucom /* validate the arguments */ 2088badb3aSMike Baucom if (!regfile) { 2188badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 2288badb3aSMike Baucom return 0; /* failure */ 2388badb3aSMike Baucom } 2488badb3aSMike Baucom memset(regfile, 0, sizeof(struct ulp_regfile)); 2588badb3aSMike Baucom return 1; /* Success */ 2688badb3aSMike Baucom } 2788badb3aSMike Baucom 2888badb3aSMike Baucom /* 2988badb3aSMike Baucom * Read a value from the regfile 3088badb3aSMike Baucom * 3188badb3aSMike Baucom * regfile [in] The regfile instance. Must be initialized prior to being used 3288badb3aSMike Baucom * 3388badb3aSMike Baucom * field [in] The field to be read within the regfile. 3488badb3aSMike Baucom * 3588badb3aSMike Baucom * data [in/out] 3688badb3aSMike Baucom * 3788badb3aSMike Baucom * returns size, zero on failure 3888badb3aSMike Baucom */ 3988badb3aSMike Baucom uint32_t 4088badb3aSMike Baucom ulp_regfile_read(struct ulp_regfile *regfile, 4188badb3aSMike Baucom enum bnxt_ulp_regfile_index field, 4288badb3aSMike Baucom uint64_t *data) 4388badb3aSMike Baucom { 4488badb3aSMike Baucom /* validate the arguments */ 4588badb3aSMike Baucom if (!regfile || field >= BNXT_ULP_REGFILE_INDEX_LAST) { 4688badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 4788badb3aSMike Baucom return 0; /* failure */ 4888badb3aSMike Baucom } 4988badb3aSMike Baucom 5088badb3aSMike Baucom *data = regfile->entry[field].data; 5188badb3aSMike Baucom return sizeof(*data); 5288badb3aSMike Baucom } 5388badb3aSMike Baucom 5488badb3aSMike Baucom /* 5588badb3aSMike Baucom * Write a value to the regfile 5688badb3aSMike Baucom * 5788badb3aSMike Baucom * regfile [in] The regfile instance. Must be initialized prior to being used 5888badb3aSMike Baucom * 5988badb3aSMike Baucom * field [in] The field to be written within the regfile. 6088badb3aSMike Baucom * 6188badb3aSMike Baucom * data [in] The value is written into this variable. It is going to be in the 6288badb3aSMike Baucom * same byte order as it was written. 6388badb3aSMike Baucom * 6488badb3aSMike Baucom * size [in] The size in bytes of the value beingritten into this 6588badb3aSMike Baucom * variable. 6688badb3aSMike Baucom * 6788badb3aSMike Baucom * returns 0 on fail 6888badb3aSMike Baucom */ 6988badb3aSMike Baucom uint32_t 7088badb3aSMike Baucom ulp_regfile_write(struct ulp_regfile *regfile, 7188badb3aSMike Baucom enum bnxt_ulp_regfile_index field, 7288badb3aSMike Baucom uint64_t data) 7388badb3aSMike Baucom { 7488badb3aSMike Baucom /* validate the arguments */ 7588badb3aSMike Baucom if (!regfile || field >= BNXT_ULP_REGFILE_INDEX_LAST) { 7688badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 7788badb3aSMike Baucom return 0; /* failure */ 7888badb3aSMike Baucom } 7988badb3aSMike Baucom 8088badb3aSMike Baucom regfile->entry[field].data = data; 8188badb3aSMike Baucom return sizeof(data); /* Success */ 8288badb3aSMike Baucom } 8388badb3aSMike Baucom 8488badb3aSMike Baucom static void 8588badb3aSMike Baucom ulp_bs_put_msb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val) 8688badb3aSMike Baucom { 8788badb3aSMike Baucom uint8_t bitoffs = bitpos % 8; 8888badb3aSMike Baucom uint16_t index = bitpos / 8; 8988badb3aSMike Baucom uint8_t mask; 9088badb3aSMike Baucom uint8_t tmp; 9188badb3aSMike Baucom int8_t shift; 9288badb3aSMike Baucom 9388badb3aSMike Baucom tmp = bs[index]; 9488badb3aSMike Baucom mask = ((uint8_t)-1 >> (8 - bitlen)); 9588badb3aSMike Baucom shift = 8 - bitoffs - bitlen; 9688badb3aSMike Baucom val &= mask; 9788badb3aSMike Baucom 9888badb3aSMike Baucom if (shift >= 0) { 9988badb3aSMike Baucom tmp &= ~(mask << shift); 10088badb3aSMike Baucom tmp |= val << shift; 10188badb3aSMike Baucom bs[index] = tmp; 10288badb3aSMike Baucom } else { 10388badb3aSMike Baucom tmp &= ~((uint8_t)-1 >> bitoffs); 10488badb3aSMike Baucom tmp |= val >> -shift; 10588badb3aSMike Baucom bs[index++] = tmp; 10688badb3aSMike Baucom 10788badb3aSMike Baucom tmp = bs[index]; 10888badb3aSMike Baucom tmp &= ((uint8_t)-1 >> (bitlen - (8 - bitoffs))); 10988badb3aSMike Baucom tmp |= val << (8 + shift); 11088badb3aSMike Baucom bs[index] = tmp; 11188badb3aSMike Baucom } 11288badb3aSMike Baucom } 11388badb3aSMike Baucom 11488badb3aSMike Baucom static void 11588badb3aSMike Baucom ulp_bs_put_lsb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val) 11688badb3aSMike Baucom { 11788badb3aSMike Baucom uint8_t bitoffs = bitpos % 8; 11888badb3aSMike Baucom uint16_t index = bitpos / 8; 11988badb3aSMike Baucom uint8_t mask; 12088badb3aSMike Baucom uint8_t tmp; 12188badb3aSMike Baucom uint8_t shift; 12288badb3aSMike Baucom uint8_t partial; 12388badb3aSMike Baucom 12488badb3aSMike Baucom tmp = bs[index]; 12588badb3aSMike Baucom shift = bitoffs; 12688badb3aSMike Baucom 12788badb3aSMike Baucom if (bitoffs + bitlen <= 8) { 12888badb3aSMike Baucom mask = ((1 << bitlen) - 1) << shift; 12988badb3aSMike Baucom tmp &= ~mask; 13088badb3aSMike Baucom tmp |= ((val << shift) & mask); 13188badb3aSMike Baucom bs[index] = tmp; 13288badb3aSMike Baucom } else { 13388badb3aSMike Baucom partial = 8 - bitoffs; 13488badb3aSMike Baucom mask = ((1 << partial) - 1) << shift; 13588badb3aSMike Baucom tmp &= ~mask; 13688badb3aSMike Baucom tmp |= ((val << shift) & mask); 13788badb3aSMike Baucom bs[index++] = tmp; 13888badb3aSMike Baucom 13988badb3aSMike Baucom val >>= partial; 14088badb3aSMike Baucom partial = bitlen - partial; 14188badb3aSMike Baucom mask = ((1 << partial) - 1); 14288badb3aSMike Baucom tmp = bs[index]; 14388badb3aSMike Baucom tmp &= ~mask; 14488badb3aSMike Baucom tmp |= (val & mask); 14588badb3aSMike Baucom bs[index] = tmp; 14688badb3aSMike Baucom } 14788badb3aSMike Baucom } 14888badb3aSMike Baucom 149*f634204bSKishore Padmanabha /* 150*f634204bSKishore Padmanabha * Add data to the byte array in Little endian format. 151*f634204bSKishore Padmanabha * 152*f634204bSKishore Padmanabha * bs [in] The byte array where data is pushed 153*f634204bSKishore Padmanabha * 154*f634204bSKishore Padmanabha * pos [in] The offset where data is pushed 155*f634204bSKishore Padmanabha * 156*f634204bSKishore Padmanabha * len [in] The number of bits to be added to the data array. 157*f634204bSKishore Padmanabha * 158*f634204bSKishore Padmanabha * val [in] The data to be added to the data array. 159*f634204bSKishore Padmanabha * 160*f634204bSKishore Padmanabha * returns the number of bits pushed. 161*f634204bSKishore Padmanabha */ 162*f634204bSKishore Padmanabha uint32_t 16388badb3aSMike Baucom ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val) 16488badb3aSMike Baucom { 16588badb3aSMike Baucom int i; 16688badb3aSMike Baucom int cnt = (len) / 8; 16788badb3aSMike Baucom int tlen = len; 16888badb3aSMike Baucom 16988badb3aSMike Baucom if (cnt > 0 && !(len % 8)) 17088badb3aSMike Baucom cnt -= 1; 17188badb3aSMike Baucom 17288badb3aSMike Baucom for (i = 0; i < cnt; i++) { 17388badb3aSMike Baucom ulp_bs_put_lsb(bs, pos, 8, val[cnt - i]); 17488badb3aSMike Baucom pos += 8; 17588badb3aSMike Baucom tlen -= 8; 17688badb3aSMike Baucom } 17788badb3aSMike Baucom 17888badb3aSMike Baucom /* Handle the remainder bits */ 17988badb3aSMike Baucom if (tlen) 18088badb3aSMike Baucom ulp_bs_put_lsb(bs, pos, tlen, val[0]); 18188badb3aSMike Baucom return len; 18288badb3aSMike Baucom } 18388badb3aSMike Baucom 184*f634204bSKishore Padmanabha /* 185*f634204bSKishore Padmanabha * Add data to the byte array in Big endian format. 186*f634204bSKishore Padmanabha * 187*f634204bSKishore Padmanabha * bs [in] The byte array where data is pushed 188*f634204bSKishore Padmanabha * 189*f634204bSKishore Padmanabha * pos [in] The offset where data is pushed 190*f634204bSKishore Padmanabha * 191*f634204bSKishore Padmanabha * len [in] The number of bits to be added to the data array. 192*f634204bSKishore Padmanabha * 193*f634204bSKishore Padmanabha * val [in] The data to be added to the data array. 194*f634204bSKishore Padmanabha * 195*f634204bSKishore Padmanabha * returns the number of bits pushed. 196*f634204bSKishore Padmanabha */ 197*f634204bSKishore Padmanabha uint32_t 19888badb3aSMike Baucom ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val) 19988badb3aSMike Baucom { 20088badb3aSMike Baucom int i; 20188badb3aSMike Baucom int cnt = (len + 7) / 8; 20288badb3aSMike Baucom int tlen = len; 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 tlen -= tmp; 21488badb3aSMike Baucom 21588badb3aSMike Baucom for (i = 1; i < cnt; i++) { 21688badb3aSMike Baucom ulp_bs_put_msb(bs, pos, 8, val[i]); 21788badb3aSMike Baucom pos += 8; 21888badb3aSMike Baucom tlen -= 8; 21988badb3aSMike Baucom } 22088badb3aSMike Baucom 22188badb3aSMike Baucom return len; 22288badb3aSMike Baucom } 22388badb3aSMike Baucom 22488badb3aSMike Baucom /* 22588badb3aSMike Baucom * Initializes the blob structure for creating binary blob 22688badb3aSMike Baucom * 22788badb3aSMike Baucom * blob [in] The blob to be initialized 22888badb3aSMike Baucom * 22988badb3aSMike Baucom * bitlen [in] The bit length of the blob 23088badb3aSMike Baucom * 23188badb3aSMike Baucom * order [in] The byte order for the blob. Currently only supporting 23288badb3aSMike Baucom * big endian. All fields are packed with this order. 23388badb3aSMike Baucom * 23488badb3aSMike Baucom * returns 0 on error or 1 on success 23588badb3aSMike Baucom */ 23688badb3aSMike Baucom uint32_t 23788badb3aSMike Baucom ulp_blob_init(struct ulp_blob *blob, 23888badb3aSMike Baucom uint16_t bitlen, 23988badb3aSMike Baucom enum bnxt_ulp_byte_order order) 24088badb3aSMike Baucom { 24188badb3aSMike Baucom /* validate the arguments */ 24288badb3aSMike Baucom if (!blob || bitlen > (8 * sizeof(blob->data))) { 24388badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 24488badb3aSMike Baucom return 0; /* failure */ 24588badb3aSMike Baucom } 24688badb3aSMike Baucom blob->bitlen = bitlen; 24788badb3aSMike Baucom blob->byte_order = order; 24888badb3aSMike Baucom blob->write_idx = 0; 24988badb3aSMike Baucom memset(blob->data, 0, sizeof(blob->data)); 25088badb3aSMike Baucom return 1; /* Success */ 25188badb3aSMike Baucom } 25288badb3aSMike Baucom 25388badb3aSMike Baucom /* 25488badb3aSMike Baucom * Add data to the binary blob at the current offset. 25588badb3aSMike Baucom * 25688badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 25788badb3aSMike Baucom * be initialized prior to pushing data. 25888badb3aSMike Baucom * 25988badb3aSMike Baucom * data [in] A pointer to bytes to be added to the blob. 26088badb3aSMike Baucom * 26188badb3aSMike Baucom * datalen [in] The number of bits to be added to the blob. 26288badb3aSMike Baucom * 26388badb3aSMike Baucom * The offset of the data is updated after each push of data. 26488badb3aSMike Baucom * NULL returned on error. 26588badb3aSMike Baucom */ 26688badb3aSMike Baucom #define ULP_BLOB_BYTE 8 26788badb3aSMike Baucom #define ULP_BLOB_BYTE_HEX 0xFF 26888badb3aSMike Baucom #define BLOB_MASK_CAL(x) ((0xFF << (x)) & 0xFF) 26988badb3aSMike Baucom uint32_t 27088badb3aSMike Baucom ulp_blob_push(struct ulp_blob *blob, 27188badb3aSMike Baucom uint8_t *data, 27288badb3aSMike Baucom uint32_t datalen) 27388badb3aSMike Baucom { 27488badb3aSMike Baucom uint32_t rc; 27588badb3aSMike Baucom 27688badb3aSMike Baucom /* validate the arguments */ 27788badb3aSMike Baucom if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx)) { 27888badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 27988badb3aSMike Baucom return 0; /* failure */ 28088badb3aSMike Baucom } 28188badb3aSMike Baucom 28288badb3aSMike Baucom if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) 28388badb3aSMike Baucom rc = ulp_bs_push_msb(blob->data, 28488badb3aSMike Baucom blob->write_idx, 28588badb3aSMike Baucom datalen, 28688badb3aSMike Baucom data); 28788badb3aSMike Baucom else 28888badb3aSMike Baucom rc = ulp_bs_push_lsb(blob->data, 28988badb3aSMike Baucom blob->write_idx, 29088badb3aSMike Baucom datalen, 29188badb3aSMike Baucom data); 29288badb3aSMike Baucom if (!rc) { 29388badb3aSMike Baucom BNXT_TF_DBG(ERR, "Failed ro write blob\n"); 29488badb3aSMike Baucom return 0; 29588badb3aSMike Baucom } 29688badb3aSMike Baucom blob->write_idx += datalen; 29788badb3aSMike Baucom return datalen; 29888badb3aSMike Baucom } 29988badb3aSMike Baucom 30088badb3aSMike Baucom /* 3017e604e7fSKishore Padmanabha * Insert data into the binary blob at the given offset. 3027e604e7fSKishore Padmanabha * 3037e604e7fSKishore Padmanabha * blob [in] The blob that data is added to. The blob must 3047e604e7fSKishore Padmanabha * be initialized prior to pushing data. 3057e604e7fSKishore Padmanabha * 3067e604e7fSKishore Padmanabha * offset [in] The offset where the data needs to be inserted. 3077e604e7fSKishore Padmanabha * 3087e604e7fSKishore Padmanabha * data [in/out] A pointer to bytes to be added to the blob. 3097e604e7fSKishore Padmanabha * 3107e604e7fSKishore Padmanabha * datalen [in] The number of bits to be added to the blob. 3117e604e7fSKishore Padmanabha * 3127e604e7fSKishore Padmanabha * The offset of the data is updated after each push of data. 3137e604e7fSKishore Padmanabha * NULL returned on error. 3147e604e7fSKishore Padmanabha */ 3157e604e7fSKishore Padmanabha uint32_t 3167e604e7fSKishore Padmanabha ulp_blob_insert(struct ulp_blob *blob, uint32_t offset, 3177e604e7fSKishore Padmanabha uint8_t *data, uint32_t datalen) 3187e604e7fSKishore Padmanabha { 3197e604e7fSKishore Padmanabha uint32_t rc; 3207e604e7fSKishore Padmanabha uint8_t local_data[BNXT_ULP_FLMP_BLOB_SIZE]; 3217e604e7fSKishore Padmanabha uint16_t mov_len; 3227e604e7fSKishore Padmanabha 3237e604e7fSKishore Padmanabha /* validate the arguments */ 3247e604e7fSKishore Padmanabha if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx) || 3257e604e7fSKishore Padmanabha offset > blob->write_idx) { 3267e604e7fSKishore Padmanabha BNXT_TF_DBG(ERR, "invalid argument\n"); 3277e604e7fSKishore Padmanabha return 0; /* failure */ 3287e604e7fSKishore Padmanabha } 3297e604e7fSKishore Padmanabha 3307e604e7fSKishore Padmanabha mov_len = blob->write_idx - offset; 3317e604e7fSKishore Padmanabha /* If offset and data len are not 8 bit aligned then return error */ 3327e604e7fSKishore Padmanabha if (ULP_BITS_IS_BYTE_NOT_ALIGNED(offset) || 3337e604e7fSKishore Padmanabha ULP_BITS_IS_BYTE_NOT_ALIGNED(datalen)) { 3347e604e7fSKishore Padmanabha BNXT_TF_DBG(ERR, "invalid argument, not aligned\n"); 3357e604e7fSKishore Padmanabha return 0; /* failure */ 3367e604e7fSKishore Padmanabha } 3377e604e7fSKishore Padmanabha 3387e604e7fSKishore Padmanabha /* copy the data so we can move the data */ 3397e604e7fSKishore Padmanabha memcpy(local_data, &blob->data[ULP_BITS_2_BYTE_NR(offset)], 3407e604e7fSKishore Padmanabha ULP_BITS_2_BYTE(mov_len)); 3417e604e7fSKishore Padmanabha blob->write_idx = offset; 3427e604e7fSKishore Padmanabha if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) 3437e604e7fSKishore Padmanabha rc = ulp_bs_push_msb(blob->data, 3447e604e7fSKishore Padmanabha blob->write_idx, 3457e604e7fSKishore Padmanabha datalen, 3467e604e7fSKishore Padmanabha data); 3477e604e7fSKishore Padmanabha else 3487e604e7fSKishore Padmanabha rc = ulp_bs_push_lsb(blob->data, 3497e604e7fSKishore Padmanabha blob->write_idx, 3507e604e7fSKishore Padmanabha datalen, 3517e604e7fSKishore Padmanabha data); 3527e604e7fSKishore Padmanabha if (!rc) { 3537e604e7fSKishore Padmanabha BNXT_TF_DBG(ERR, "Failed ro write blob\n"); 3547e604e7fSKishore Padmanabha return 0; 3557e604e7fSKishore Padmanabha } 3567e604e7fSKishore Padmanabha /* copy the previously stored data */ 3577e604e7fSKishore Padmanabha memcpy(&blob->data[ULP_BITS_2_BYTE_NR(offset + datalen)], local_data, 3587e604e7fSKishore Padmanabha ULP_BITS_2_BYTE(mov_len)); 3597e604e7fSKishore Padmanabha blob->write_idx += (mov_len + datalen); 3607e604e7fSKishore Padmanabha return datalen; 3617e604e7fSKishore Padmanabha } 3627e604e7fSKishore Padmanabha 3637e604e7fSKishore Padmanabha /* 36488badb3aSMike Baucom * Add data to the binary blob at the current offset. 36588badb3aSMike Baucom * 36688badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 36788badb3aSMike Baucom * be initialized prior to pushing data. 36888badb3aSMike Baucom * 36988badb3aSMike Baucom * data [in] 64-bit value to be added to the blob. 37088badb3aSMike Baucom * 37188badb3aSMike Baucom * datalen [in] The number of bits to be added to the blob. 37288badb3aSMike Baucom * 37388badb3aSMike Baucom * The offset of the data is updated after each push of data. 37488badb3aSMike Baucom * NULL returned on error, pointer pushed value otherwise. 37588badb3aSMike Baucom */ 37688badb3aSMike Baucom uint8_t * 37788badb3aSMike Baucom ulp_blob_push_64(struct ulp_blob *blob, 37888badb3aSMike Baucom uint64_t *data, 37988badb3aSMike Baucom uint32_t datalen) 38088badb3aSMike Baucom { 38188badb3aSMike Baucom uint8_t *val = (uint8_t *)data; 38288badb3aSMike Baucom int rc; 38388badb3aSMike Baucom 38488badb3aSMike Baucom int size = (datalen + 7) / 8; 38588badb3aSMike Baucom 38688badb3aSMike Baucom if (!blob || !data || 38788badb3aSMike Baucom datalen > (uint32_t)(blob->bitlen - blob->write_idx)) { 38888badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 38988badb3aSMike Baucom return 0; 39088badb3aSMike Baucom } 39188badb3aSMike Baucom 39288badb3aSMike Baucom rc = ulp_blob_push(blob, &val[8 - size], datalen); 39388badb3aSMike Baucom if (!rc) 39488badb3aSMike Baucom return 0; 39588badb3aSMike Baucom 39688badb3aSMike Baucom return &val[8 - size]; 39788badb3aSMike Baucom } 39888badb3aSMike Baucom 39988badb3aSMike Baucom /* 400a2be13e1SKishore Padmanabha * Add data to the binary blob at the current offset. 401a2be13e1SKishore Padmanabha * 402a2be13e1SKishore Padmanabha * blob [in] The blob that data is added to. The blob must 403a2be13e1SKishore Padmanabha * be initialized prior to pushing data. 404a2be13e1SKishore Padmanabha * 405a2be13e1SKishore Padmanabha * data [in] 32-bit value to be added to the blob. 406a2be13e1SKishore Padmanabha * 407a2be13e1SKishore Padmanabha * datalen [in] The number of bits to be added ot the blob. 408a2be13e1SKishore Padmanabha * 409a2be13e1SKishore Padmanabha * The offset of the data is updated after each push of data. 410a2be13e1SKishore Padmanabha * NULL returned on error, pointer pushed value otherwise. 411a2be13e1SKishore Padmanabha */ 412a2be13e1SKishore Padmanabha uint8_t * 413a2be13e1SKishore Padmanabha ulp_blob_push_32(struct ulp_blob *blob, 414a2be13e1SKishore Padmanabha uint32_t *data, 415a2be13e1SKishore Padmanabha uint32_t datalen) 416a2be13e1SKishore Padmanabha { 417a2be13e1SKishore Padmanabha uint8_t *val = (uint8_t *)data; 418a2be13e1SKishore Padmanabha uint32_t rc; 419a2be13e1SKishore Padmanabha uint32_t size = ULP_BITS_2_BYTE(datalen); 420a2be13e1SKishore Padmanabha 421a2be13e1SKishore Padmanabha if (!data || size > sizeof(uint32_t)) { 422a2be13e1SKishore Padmanabha BNXT_TF_DBG(ERR, "invalid argument\n"); 423a2be13e1SKishore Padmanabha return 0; 424a2be13e1SKishore Padmanabha } 425a2be13e1SKishore Padmanabha 426a2be13e1SKishore Padmanabha rc = ulp_blob_push(blob, &val[sizeof(uint32_t) - size], datalen); 427a2be13e1SKishore Padmanabha if (!rc) 428a2be13e1SKishore Padmanabha return 0; 429a2be13e1SKishore Padmanabha 430a2be13e1SKishore Padmanabha return &val[sizeof(uint32_t) - size]; 431a2be13e1SKishore Padmanabha } 432a2be13e1SKishore Padmanabha 433a2be13e1SKishore Padmanabha /* 43488badb3aSMike Baucom * Add encap data to the binary blob at the current offset. 43588badb3aSMike Baucom * 43688badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 43788badb3aSMike Baucom * be initialized prior to pushing data. 43888badb3aSMike Baucom * 43988badb3aSMike Baucom * data [in] value to be added to the blob. 44088badb3aSMike Baucom * 44188badb3aSMike Baucom * datalen [in] The number of bits to be added to the blob. 44288badb3aSMike Baucom * 44388badb3aSMike Baucom * The offset of the data is updated after each push of data. 44488badb3aSMike Baucom * NULL returned on error, pointer pushed value otherwise. 44588badb3aSMike Baucom */ 44688badb3aSMike Baucom uint32_t 44788badb3aSMike Baucom ulp_blob_push_encap(struct ulp_blob *blob, 44888badb3aSMike Baucom uint8_t *data, 44988badb3aSMike Baucom uint32_t datalen) 45088badb3aSMike Baucom { 45188badb3aSMike Baucom uint8_t *val = (uint8_t *)data; 45288badb3aSMike Baucom uint32_t initial_size, write_size = datalen; 45388badb3aSMike Baucom uint32_t size = 0; 45488badb3aSMike Baucom 45588badb3aSMike Baucom if (!blob || !data || 45688badb3aSMike Baucom datalen > (uint32_t)(blob->bitlen - blob->write_idx)) { 45788badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 45888badb3aSMike Baucom return 0; 45988badb3aSMike Baucom } 46088badb3aSMike Baucom 46188badb3aSMike Baucom initial_size = ULP_BYTE_2_BITS(sizeof(uint64_t)) - 46288badb3aSMike Baucom (blob->write_idx % ULP_BYTE_2_BITS(sizeof(uint64_t))); 46388badb3aSMike Baucom while (write_size > 0) { 46488badb3aSMike Baucom if (initial_size && write_size > initial_size) { 46588badb3aSMike Baucom size = initial_size; 46688badb3aSMike Baucom initial_size = 0; 46788badb3aSMike Baucom } else if (initial_size && write_size <= initial_size) { 46888badb3aSMike Baucom size = write_size; 46988badb3aSMike Baucom initial_size = 0; 47088badb3aSMike Baucom } else if (write_size > ULP_BYTE_2_BITS(sizeof(uint64_t))) { 47188badb3aSMike Baucom size = ULP_BYTE_2_BITS(sizeof(uint64_t)); 47288badb3aSMike Baucom } else { 47388badb3aSMike Baucom size = write_size; 47488badb3aSMike Baucom } 47588badb3aSMike Baucom if (!ulp_blob_push(blob, val, size)) { 47688badb3aSMike Baucom BNXT_TF_DBG(ERR, "push field failed\n"); 47788badb3aSMike Baucom return 0; 47888badb3aSMike Baucom } 47988badb3aSMike Baucom val += ULP_BITS_2_BYTE(size); 48088badb3aSMike Baucom write_size -= size; 48188badb3aSMike Baucom } 48288badb3aSMike Baucom return datalen; 48388badb3aSMike Baucom } 48488badb3aSMike Baucom 48588badb3aSMike Baucom /* 48688badb3aSMike Baucom * Adds pad to an initialized blob at the current offset 48788badb3aSMike Baucom * 48888badb3aSMike Baucom * blob [in] The blob that data is added to. The blob must 48988badb3aSMike Baucom * be initialized prior to pushing data. 49088badb3aSMike Baucom * 49188badb3aSMike Baucom * datalen [in] The number of bits of pad to add 49288badb3aSMike Baucom * 493a4651725SMike Baucom * returns the number of pad bits added, -1 on failure 49488badb3aSMike Baucom */ 495a4651725SMike Baucom int32_t 49688badb3aSMike Baucom ulp_blob_pad_push(struct ulp_blob *blob, 49788badb3aSMike Baucom uint32_t datalen) 49888badb3aSMike Baucom { 49988badb3aSMike Baucom if (datalen > (uint32_t)(blob->bitlen - blob->write_idx)) { 50088badb3aSMike Baucom BNXT_TF_DBG(ERR, "Pad too large for blob\n"); 501*f634204bSKishore Padmanabha return -1; 50288badb3aSMike Baucom } 50388badb3aSMike Baucom 50488badb3aSMike Baucom blob->write_idx += datalen; 50588badb3aSMike Baucom return datalen; 50688badb3aSMike Baucom } 50788badb3aSMike Baucom 508afd35335SKishore Padmanabha /* Get data from src and put into dst using little-endian format */ 509afd35335SKishore Padmanabha static void 510afd35335SKishore Padmanabha ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst) 511afd35335SKishore Padmanabha { 512afd35335SKishore Padmanabha uint8_t bitoffs = bitpos % ULP_BLOB_BYTE; 513afd35335SKishore Padmanabha uint16_t index = ULP_BITS_2_BYTE_NR(bitpos); 514afd35335SKishore Padmanabha uint8_t mask, partial, shift; 515afd35335SKishore Padmanabha 516afd35335SKishore Padmanabha shift = bitoffs; 517afd35335SKishore Padmanabha partial = ULP_BLOB_BYTE - bitoffs; 518afd35335SKishore Padmanabha if (bitoffs + bitlen <= ULP_BLOB_BYTE) { 519afd35335SKishore Padmanabha mask = ((1 << bitlen) - 1) << shift; 520afd35335SKishore Padmanabha *dst = (src[index] & mask) >> shift; 521afd35335SKishore Padmanabha } else { 522afd35335SKishore Padmanabha mask = ((1 << partial) - 1) << shift; 523afd35335SKishore Padmanabha *dst = (src[index] & mask) >> shift; 524afd35335SKishore Padmanabha index++; 525afd35335SKishore Padmanabha partial = bitlen - partial; 526afd35335SKishore Padmanabha mask = ((1 << partial) - 1); 527afd35335SKishore Padmanabha *dst |= (src[index] & mask) << (ULP_BLOB_BYTE - bitoffs); 528afd35335SKishore Padmanabha } 529afd35335SKishore Padmanabha } 530afd35335SKishore Padmanabha 531*f634204bSKishore Padmanabha /* 532*f634204bSKishore Padmanabha * Get data from the byte array in Little endian format. 533*f634204bSKishore Padmanabha * 534*f634204bSKishore Padmanabha * src [in] The byte array where data is extracted from 535*f634204bSKishore Padmanabha * 536*f634204bSKishore Padmanabha * dst [out] The byte array where data is pulled into 537*f634204bSKishore Padmanabha * 538*f634204bSKishore Padmanabha * size [in] The size of dst array in bytes 539*f634204bSKishore Padmanabha * 540*f634204bSKishore Padmanabha * offset [in] The offset where data is pulled 541*f634204bSKishore Padmanabha * 542*f634204bSKishore Padmanabha * len [in] The number of bits to be extracted from the data array 543*f634204bSKishore Padmanabha * 544*f634204bSKishore Padmanabha * returns None. 545*f634204bSKishore Padmanabha */ 546*f634204bSKishore Padmanabha void 547afd35335SKishore Padmanabha ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size, 548afd35335SKishore Padmanabha uint32_t offset, uint32_t len) 549afd35335SKishore Padmanabha { 550afd35335SKishore Padmanabha uint32_t idx; 551afd35335SKishore Padmanabha uint32_t cnt = ULP_BITS_2_BYTE_NR(len); 552afd35335SKishore Padmanabha 553afd35335SKishore Padmanabha /* iterate bytewise to get data */ 554afd35335SKishore Padmanabha for (idx = 0; idx < cnt; idx++) { 555afd35335SKishore Padmanabha ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE, 556afd35335SKishore Padmanabha &dst[size - 1 - idx]); 557afd35335SKishore Padmanabha offset += ULP_BLOB_BYTE; 558afd35335SKishore Padmanabha len -= ULP_BLOB_BYTE; 559afd35335SKishore Padmanabha } 560afd35335SKishore Padmanabha 561afd35335SKishore Padmanabha /* Extract the last reminder data that is not 8 byte boundary */ 562afd35335SKishore Padmanabha if (len) 563afd35335SKishore Padmanabha ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]); 564afd35335SKishore Padmanabha } 565afd35335SKishore Padmanabha 566*f634204bSKishore Padmanabha /* Get data from src and put into dst using big-endian format */ 567*f634204bSKishore Padmanabha static void 568*f634204bSKishore Padmanabha ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst) 569*f634204bSKishore Padmanabha { 570*f634204bSKishore Padmanabha uint8_t bitoffs = bitpos % ULP_BLOB_BYTE; 571*f634204bSKishore Padmanabha uint16_t index = ULP_BITS_2_BYTE_NR(bitpos); 572*f634204bSKishore Padmanabha uint8_t mask; 573*f634204bSKishore Padmanabha int32_t shift; 574*f634204bSKishore Padmanabha 575*f634204bSKishore Padmanabha shift = ULP_BLOB_BYTE - bitoffs - bitlen; 576*f634204bSKishore Padmanabha if (shift >= 0) { 577*f634204bSKishore Padmanabha mask = 0xFF >> -bitlen; 578*f634204bSKishore Padmanabha *dst = (src[index] >> shift) & mask; 579*f634204bSKishore Padmanabha } else { 580*f634204bSKishore Padmanabha *dst = (src[index] & (0xFF >> bitoffs)) << -shift; 581*f634204bSKishore Padmanabha *dst |= src[index + 1] >> -shift; 582*f634204bSKishore Padmanabha } 583*f634204bSKishore Padmanabha } 584*f634204bSKishore Padmanabha 585*f634204bSKishore Padmanabha /* 586*f634204bSKishore Padmanabha * Get data from the byte array in Big endian format. 587*f634204bSKishore Padmanabha * 588*f634204bSKishore Padmanabha * src [in] The byte array where data is extracted from 589*f634204bSKishore Padmanabha * 590*f634204bSKishore Padmanabha * dst [out] The byte array where data is pulled into 591*f634204bSKishore Padmanabha * 592*f634204bSKishore Padmanabha * offset [in] The offset where data is pulled 593*f634204bSKishore Padmanabha * 594*f634204bSKishore Padmanabha * len [in] The number of bits to be extracted from the data array 595*f634204bSKishore Padmanabha * 596*f634204bSKishore Padmanabha * returns None. 597*f634204bSKishore Padmanabha */ 598*f634204bSKishore Padmanabha void 599*f634204bSKishore Padmanabha ulp_bs_pull_msb(uint8_t *src, uint8_t *dst, 600*f634204bSKishore Padmanabha uint32_t offset, uint32_t len) 601*f634204bSKishore Padmanabha { 602*f634204bSKishore Padmanabha uint32_t idx; 603*f634204bSKishore Padmanabha uint32_t cnt = ULP_BITS_2_BYTE_NR(len); 604*f634204bSKishore Padmanabha 605*f634204bSKishore Padmanabha /* iterate bytewise to get data */ 606*f634204bSKishore Padmanabha for (idx = 0; idx < cnt; idx++) { 607*f634204bSKishore Padmanabha ulp_bs_get_msb(src, offset, ULP_BLOB_BYTE, &dst[idx]); 608*f634204bSKishore Padmanabha offset += ULP_BLOB_BYTE; 609*f634204bSKishore Padmanabha len -= ULP_BLOB_BYTE; 610*f634204bSKishore Padmanabha } 611*f634204bSKishore Padmanabha 612*f634204bSKishore Padmanabha /* Extract the last reminder data that is not 8 byte boundary */ 613*f634204bSKishore Padmanabha if (len) 614*f634204bSKishore Padmanabha ulp_bs_get_msb(src, offset, len, &dst[idx]); 615*f634204bSKishore Padmanabha } 616*f634204bSKishore Padmanabha 617afd35335SKishore Padmanabha /* 618afd35335SKishore Padmanabha * Extract data from the binary blob using given offset. 619afd35335SKishore Padmanabha * 620afd35335SKishore Padmanabha * blob [in] The blob that data is extracted from. The blob must 621afd35335SKishore Padmanabha * be initialized prior to pulling data. 622afd35335SKishore Padmanabha * 623afd35335SKishore Padmanabha * data [in] A pointer to put the data. 624afd35335SKishore Padmanabha * data_size [in] size of the data buffer in bytes. 625afd35335SKishore Padmanabha *offset [in] - Offset in the blob to extract the data in bits format. 626afd35335SKishore Padmanabha * len [in] The number of bits to be pulled from the blob. 627afd35335SKishore Padmanabha * 628afd35335SKishore Padmanabha * Output: zero on success, -1 on failure 629afd35335SKishore Padmanabha */ 630afd35335SKishore Padmanabha int32_t 631afd35335SKishore Padmanabha ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size, 632afd35335SKishore Padmanabha uint16_t offset, uint16_t len) 633afd35335SKishore Padmanabha { 634afd35335SKishore Padmanabha /* validate the arguments */ 635afd35335SKishore Padmanabha if (!blob || (offset + len) > blob->bitlen || 636afd35335SKishore Padmanabha ULP_BYTE_2_BITS(data_size) < len) { 637afd35335SKishore Padmanabha BNXT_TF_DBG(ERR, "invalid argument\n"); 638afd35335SKishore Padmanabha return -1; /* failure */ 639afd35335SKishore Padmanabha } 640afd35335SKishore Padmanabha 641*f634204bSKishore Padmanabha if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) 642*f634204bSKishore Padmanabha ulp_bs_pull_msb(blob->data, data, offset, len); 643*f634204bSKishore Padmanabha else 644afd35335SKishore Padmanabha ulp_bs_pull_lsb(blob->data, data, data_size, offset, len); 645afd35335SKishore Padmanabha return 0; 646afd35335SKishore Padmanabha } 647afd35335SKishore Padmanabha 64888badb3aSMike Baucom /* 64988badb3aSMike Baucom * Get the data portion of the binary blob. 65088badb3aSMike Baucom * 65188badb3aSMike Baucom * blob [in] The blob's data to be retrieved. The blob must be 65288badb3aSMike Baucom * initialized prior to pushing data. 65388badb3aSMike Baucom * 65488badb3aSMike Baucom * datalen [out] The number of bits to that are filled. 65588badb3aSMike Baucom * 65688badb3aSMike Baucom * returns a byte array of the blob data. Returns NULL on error. 65788badb3aSMike Baucom */ 65888badb3aSMike Baucom uint8_t * 65988badb3aSMike Baucom ulp_blob_data_get(struct ulp_blob *blob, 66088badb3aSMike Baucom uint16_t *datalen) 66188badb3aSMike Baucom { 66288badb3aSMike Baucom /* validate the arguments */ 66388badb3aSMike Baucom if (!blob) { 66488badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 66588badb3aSMike Baucom return NULL; /* failure */ 66688badb3aSMike Baucom } 66788badb3aSMike Baucom *datalen = blob->write_idx; 66888badb3aSMike Baucom return blob->data; 66988badb3aSMike Baucom } 67088badb3aSMike Baucom 67188badb3aSMike Baucom /* 67288badb3aSMike Baucom * Set the encap swap start index of the binary blob. 67388badb3aSMike Baucom * 67488badb3aSMike Baucom * blob [in] The blob's data to be retrieved. The blob must be 67588badb3aSMike Baucom * initialized prior to pushing data. 67688badb3aSMike Baucom * 67788badb3aSMike Baucom * returns void. 67888badb3aSMike Baucom */ 67988badb3aSMike Baucom void 68088badb3aSMike Baucom ulp_blob_encap_swap_idx_set(struct ulp_blob *blob) 68188badb3aSMike Baucom { 68288badb3aSMike Baucom /* validate the arguments */ 68388badb3aSMike Baucom if (!blob) { 68488badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 68588badb3aSMike Baucom return; /* failure */ 68688badb3aSMike Baucom } 68788badb3aSMike Baucom blob->encap_swap_idx = blob->write_idx; 68888badb3aSMike Baucom } 68988badb3aSMike Baucom 69088badb3aSMike Baucom /* 69188badb3aSMike Baucom * Perform the encap buffer swap to 64 bit reversal. 69288badb3aSMike Baucom * 69388badb3aSMike Baucom * blob [in] The blob's data to be used for swap. 69488badb3aSMike Baucom * 69588badb3aSMike Baucom * returns void. 69688badb3aSMike Baucom */ 69788badb3aSMike Baucom void 69888badb3aSMike Baucom ulp_blob_perform_encap_swap(struct ulp_blob *blob) 69988badb3aSMike Baucom { 7009238ac2aSKishore Padmanabha uint32_t i, idx = 0, end_idx = 0, roundoff; 70188badb3aSMike Baucom uint8_t temp_val_1, temp_val_2; 70288badb3aSMike Baucom 70388badb3aSMike Baucom /* validate the arguments */ 70488badb3aSMike Baucom if (!blob) { 70588badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 70688badb3aSMike Baucom return; /* failure */ 70788badb3aSMike Baucom } 708f0ca77fdSMike Baucom idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx); 70988badb3aSMike Baucom end_idx = ULP_BITS_2_BYTE(blob->write_idx); 7109238ac2aSKishore Padmanabha roundoff = ULP_BYTE_2_BITS(ULP_BITS_2_BYTE(end_idx)); 7119238ac2aSKishore Padmanabha if (roundoff > end_idx) { 7129238ac2aSKishore Padmanabha blob->write_idx += ULP_BYTE_2_BITS(roundoff - end_idx); 7139238ac2aSKishore Padmanabha end_idx = roundoff; 7149238ac2aSKishore Padmanabha } 71588badb3aSMike Baucom while (idx <= end_idx) { 71688badb3aSMike Baucom for (i = 0; i < 4; i = i + 2) { 71788badb3aSMike Baucom temp_val_1 = blob->data[idx + i]; 71888badb3aSMike Baucom temp_val_2 = blob->data[idx + i + 1]; 71988badb3aSMike Baucom blob->data[idx + i] = blob->data[idx + 6 - i]; 72088badb3aSMike Baucom blob->data[idx + i + 1] = blob->data[idx + 7 - i]; 72188badb3aSMike Baucom blob->data[idx + 7 - i] = temp_val_2; 72288badb3aSMike Baucom blob->data[idx + 6 - i] = temp_val_1; 72388badb3aSMike Baucom } 72488badb3aSMike Baucom idx += 8; 72588badb3aSMike Baucom } 72688badb3aSMike Baucom } 72788badb3aSMike Baucom 72888badb3aSMike Baucom /* 729a4651725SMike Baucom * Perform the blob buffer reversal byte wise. 730a4651725SMike Baucom * This api makes the first byte the last and 731a4651725SMike Baucom * vice-versa. 732a4651725SMike Baucom * 733a4651725SMike Baucom * blob [in] The blob's data to be used for swap. 734a4651725SMike Baucom * 735a4651725SMike Baucom * returns void. 736a4651725SMike Baucom */ 737a4651725SMike Baucom void 738a4651725SMike Baucom ulp_blob_perform_byte_reverse(struct ulp_blob *blob) 739a4651725SMike Baucom { 740a4651725SMike Baucom uint32_t idx = 0, num = 0; 741a4651725SMike Baucom uint8_t xchar; 742a4651725SMike Baucom 743a4651725SMike Baucom /* validate the arguments */ 744a4651725SMike Baucom if (!blob) { 745a4651725SMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 746a4651725SMike Baucom return; /* failure */ 747a4651725SMike Baucom } 748a4651725SMike Baucom 749a4651725SMike Baucom num = ULP_BITS_2_BYTE_NR(blob->write_idx); 750a4651725SMike Baucom for (idx = 0; idx < (num / 2); idx++) { 751a4651725SMike Baucom xchar = blob->data[idx]; 752a4651725SMike Baucom blob->data[idx] = blob->data[(num - 1) - idx]; 753a4651725SMike Baucom blob->data[(num - 1) - idx] = xchar; 754a4651725SMike Baucom } 755a4651725SMike Baucom } 756a4651725SMike Baucom 757a4651725SMike Baucom /* 7587e604e7fSKishore Padmanabha * Perform the blob buffer 64 bit word swap. 7597e604e7fSKishore Padmanabha * This api makes the first 4 bytes the last in 7607e604e7fSKishore Padmanabha * a given 64 bit value and vice-versa. 7617e604e7fSKishore Padmanabha * 7627e604e7fSKishore Padmanabha * blob [in] The blob's data to be used for swap. 7637e604e7fSKishore Padmanabha * 7647e604e7fSKishore Padmanabha * returns void. 7657e604e7fSKishore Padmanabha */ 7667e604e7fSKishore Padmanabha void 7677e604e7fSKishore Padmanabha ulp_blob_perform_64B_word_swap(struct ulp_blob *blob) 7687e604e7fSKishore Padmanabha { 7697e604e7fSKishore Padmanabha uint32_t i, j, num; 7707e604e7fSKishore Padmanabha uint8_t xchar; 7717e604e7fSKishore Padmanabha uint32_t word_size = ULP_64B_IN_BYTES / 2; 7727e604e7fSKishore Padmanabha 7737e604e7fSKishore Padmanabha /* validate the arguments */ 7747e604e7fSKishore Padmanabha if (!blob) { 7757e604e7fSKishore Padmanabha BNXT_TF_DBG(ERR, "invalid argument\n"); 7767e604e7fSKishore Padmanabha return; /* failure */ 7777e604e7fSKishore Padmanabha } 7787e604e7fSKishore Padmanabha num = ULP_BITS_2_BYTE(blob->write_idx); 7797e604e7fSKishore Padmanabha for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) { 7807e604e7fSKishore Padmanabha for (j = 0; j < word_size; j++) { 7817e604e7fSKishore Padmanabha xchar = blob->data[i + j]; 7827e604e7fSKishore Padmanabha blob->data[i + j] = blob->data[i + j + word_size]; 7837e604e7fSKishore Padmanabha blob->data[i + j + word_size] = xchar; 7847e604e7fSKishore Padmanabha } 7857e604e7fSKishore Padmanabha } 7867e604e7fSKishore Padmanabha } 7877e604e7fSKishore Padmanabha 7887e604e7fSKishore Padmanabha /* 7897e604e7fSKishore Padmanabha * Perform the blob buffer 64 bit byte swap. 7907e604e7fSKishore Padmanabha * This api makes the first byte the last in 7917e604e7fSKishore Padmanabha * a given 64 bit value and vice-versa. 7927e604e7fSKishore Padmanabha * 7937e604e7fSKishore Padmanabha * blob [in] The blob's data to be used for swap. 7947e604e7fSKishore Padmanabha * 7957e604e7fSKishore Padmanabha * returns void. 7967e604e7fSKishore Padmanabha */ 7977e604e7fSKishore Padmanabha void 7987e604e7fSKishore Padmanabha ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob) 7997e604e7fSKishore Padmanabha { 8007e604e7fSKishore Padmanabha uint32_t i, j, num; 8017e604e7fSKishore Padmanabha uint8_t xchar; 8027e604e7fSKishore Padmanabha uint32_t offset = ULP_64B_IN_BYTES - 1; 8037e604e7fSKishore Padmanabha 8047e604e7fSKishore Padmanabha /* validate the arguments */ 8057e604e7fSKishore Padmanabha if (!blob) { 8067e604e7fSKishore Padmanabha BNXT_TF_DBG(ERR, "invalid argument\n"); 8077e604e7fSKishore Padmanabha return; /* failure */ 8087e604e7fSKishore Padmanabha } 8097e604e7fSKishore Padmanabha num = ULP_BITS_2_BYTE(blob->write_idx); 8107e604e7fSKishore Padmanabha for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) { 8117e604e7fSKishore Padmanabha for (j = 0; j < (ULP_64B_IN_BYTES / 2); j++) { 8127e604e7fSKishore Padmanabha xchar = blob->data[i + j]; 8137e604e7fSKishore Padmanabha blob->data[i + j] = blob->data[i + offset - j]; 8147e604e7fSKishore Padmanabha blob->data[i + offset - j] = xchar; 8157e604e7fSKishore Padmanabha } 8167e604e7fSKishore Padmanabha } 8177e604e7fSKishore Padmanabha } 8187e604e7fSKishore Padmanabha 8197e604e7fSKishore Padmanabha /* 82088badb3aSMike Baucom * Read data from the operand 82188badb3aSMike Baucom * 82288badb3aSMike Baucom * operand [in] A pointer to a 16 Byte operand 82388badb3aSMike Baucom * 82488badb3aSMike Baucom * val [in/out] The variable to copy the operand to 82588badb3aSMike Baucom * 82688badb3aSMike Baucom * bytes [in] The number of bytes to read into val 82788badb3aSMike Baucom * 82888badb3aSMike Baucom * returns number of bits read, zero on error 82988badb3aSMike Baucom */ 83088badb3aSMike Baucom uint16_t 83188badb3aSMike Baucom ulp_operand_read(uint8_t *operand, 83288badb3aSMike Baucom uint8_t *val, 83388badb3aSMike Baucom uint16_t bytes) 83488badb3aSMike Baucom { 83588badb3aSMike Baucom /* validate the arguments */ 83688badb3aSMike Baucom if (!operand || !val) { 83788badb3aSMike Baucom BNXT_TF_DBG(ERR, "invalid argument\n"); 83888badb3aSMike Baucom return 0; /* failure */ 83988badb3aSMike Baucom } 84088badb3aSMike Baucom memcpy(val, operand, bytes); 84188badb3aSMike Baucom return bytes; 84288badb3aSMike Baucom } 84388badb3aSMike Baucom 84488badb3aSMike Baucom /* 84588badb3aSMike Baucom * copy the buffer in the encap format which is 2 bytes. 84688badb3aSMike Baucom * The MSB of the src is placed at the LSB of dst. 84788badb3aSMike Baucom * 84888badb3aSMike Baucom * dst [out] The destination buffer 84988badb3aSMike Baucom * src [in] The source buffer dst 85088badb3aSMike Baucom * size[in] size of the buffer. 8519238ac2aSKishore Padmanabha * align[in] The alignment is either 8 or 16. 85288badb3aSMike Baucom */ 85388badb3aSMike Baucom void 85488badb3aSMike Baucom ulp_encap_buffer_copy(uint8_t *dst, 85588badb3aSMike Baucom const uint8_t *src, 8569238ac2aSKishore Padmanabha uint16_t size, 8579238ac2aSKishore Padmanabha uint16_t align) 85888badb3aSMike Baucom { 8599238ac2aSKishore Padmanabha uint16_t idx, tmp_size = 0; 86088badb3aSMike Baucom 8619238ac2aSKishore Padmanabha do { 8629238ac2aSKishore Padmanabha dst += tmp_size; 8639238ac2aSKishore Padmanabha src += tmp_size; 8649238ac2aSKishore Padmanabha idx = 0; 8659238ac2aSKishore Padmanabha if (size > align) { 8669238ac2aSKishore Padmanabha tmp_size = align; 8679238ac2aSKishore Padmanabha size -= align; 8689238ac2aSKishore Padmanabha } else { 8699238ac2aSKishore Padmanabha tmp_size = size; 8709238ac2aSKishore Padmanabha size = 0; 8719238ac2aSKishore Padmanabha } 87288badb3aSMike Baucom /* copy 2 bytes at a time. Write MSB to LSB */ 8739238ac2aSKishore Padmanabha while ((idx + sizeof(uint16_t)) <= tmp_size) { 8749238ac2aSKishore Padmanabha memcpy(&dst[idx], 8759238ac2aSKishore Padmanabha &src[tmp_size - idx - sizeof(uint16_t)], 87688badb3aSMike Baucom sizeof(uint16_t)); 87788badb3aSMike Baucom idx += sizeof(uint16_t); 87888badb3aSMike Baucom } 8799238ac2aSKishore Padmanabha } while (size); 88088badb3aSMike Baucom } 88188badb3aSMike Baucom 88288badb3aSMike Baucom /* 88388badb3aSMike Baucom * Check the buffer is empty 88488badb3aSMike Baucom * 88588badb3aSMike Baucom * buf [in] The buffer 88688badb3aSMike Baucom * size [in] The size of the buffer 88788badb3aSMike Baucom * 88888badb3aSMike Baucom */ 88988badb3aSMike Baucom int32_t ulp_buffer_is_empty(const uint8_t *buf, uint32_t size) 89088badb3aSMike Baucom { 89188badb3aSMike Baucom return buf[0] == 0 && !memcmp(buf, buf + 1, size - 1); 89288badb3aSMike Baucom } 8932bbcdee8SKishore Padmanabha 8942bbcdee8SKishore Padmanabha /* Function to check if bitmap is zero.Return 1 on success */ 8952bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_is_zero(uint8_t *bitmap, int32_t size) 8962bbcdee8SKishore Padmanabha { 8972bbcdee8SKishore Padmanabha while (size-- > 0) { 8982bbcdee8SKishore Padmanabha if (*bitmap != 0) 8992bbcdee8SKishore Padmanabha return 0; 9002bbcdee8SKishore Padmanabha bitmap++; 9012bbcdee8SKishore Padmanabha } 9022bbcdee8SKishore Padmanabha return 1; 9032bbcdee8SKishore Padmanabha } 9042bbcdee8SKishore Padmanabha 9052bbcdee8SKishore Padmanabha /* Function to check if bitmap is ones. Return 1 on success */ 9062bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size) 9072bbcdee8SKishore Padmanabha { 9082bbcdee8SKishore Padmanabha while (size-- > 0) { 9092bbcdee8SKishore Padmanabha if (*bitmap != 0xFF) 9102bbcdee8SKishore Padmanabha return 0; 9112bbcdee8SKishore Padmanabha bitmap++; 9122bbcdee8SKishore Padmanabha } 9132bbcdee8SKishore Padmanabha return 1; 9142bbcdee8SKishore Padmanabha } 9152bbcdee8SKishore Padmanabha 9162bbcdee8SKishore Padmanabha /* Function to check if bitmap is not zero. Return 1 on success */ 9172bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_notzero(uint8_t *bitmap, int32_t size) 9182bbcdee8SKishore Padmanabha { 9192bbcdee8SKishore Padmanabha while (size-- > 0) { 9202bbcdee8SKishore Padmanabha if (*bitmap != 0) 9212bbcdee8SKishore Padmanabha return 1; 9222bbcdee8SKishore Padmanabha bitmap++; 9232bbcdee8SKishore Padmanabha } 9242bbcdee8SKishore Padmanabha return 0; 9252bbcdee8SKishore Padmanabha } 926