+int xran_parse_section_ext1(void *ext,
+ struct xran_sectionext1_info *extinfo)
+{
+ int len;
+ int total_len;
+ struct xran_cp_radioapp_section_ext1 *ext1;
+ uint8_t *data;
+ int parm_size, iq_size;
+ int N;
+ void *pHandle;
+
+ pHandle = NULL;
+ N = xran_get_conf_num_bfweights(pHandle);
+ extinfo->bfwNumber = N;
+
+ ext1 = (struct xran_cp_radioapp_section_ext1 *)ext;
+ data = (uint8_t *)ext;
+
+ len = 0;
+ total_len = ext1->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ extinfo->bfwCompMeth = ext1->bfwCompMeth;
+ extinfo->bfwiqWidth = (ext1->bfwIqWidth==0)?16:ext1->bfwIqWidth;
+
+ len += sizeof(struct xran_cp_radioapp_section_ext1);
+ data += sizeof(struct xran_cp_radioapp_section_ext1);
+
+ switch(ext1->bfwCompMeth) {
+ case XRAN_BFWCOMPMETHOD_NONE:
+ parm_size = 0;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_BLKFLOAT:
+ parm_size = 1;
+ extinfo->bfwCompParam.exponent = *data & 0x0f;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_BLKSCALE:
+ parm_size = 1;
+ extinfo->bfwCompParam.blockScaler = *data;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_ULAW:
+ parm_size = 1;
+ extinfo->bfwCompParam.compBitWidthShift = *data;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_BEAMSPACE:
+ parm_size = N>>3; if(N%8) parm_size++; parm_size *= 8;
+ rte_memcpy(data, extinfo->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
+ break;
+
+ default:
+ print_err("Invalid BfComp method - %d", ext1->bfwCompMeth);
+ parm_size = 0;
+ }
+
+ len += parm_size;
+ data += parm_size;
+
+ /* Get BF weights */
+ iq_size = N * extinfo->bfwiqWidth * 2; // total in bits
+ parm_size = iq_size>>3; // total in bytes (/8)
+ if(iq_size%8) parm_size++; // round up
+
+ //rte_memcpy(data, extinfo->p_bfwIQ, parm_size);
+ extinfo->p_bfwIQ = (int16_t*)data;
+
+ len += parm_size;
+
+ parm_size = len % XRAN_SECTIONEXT_ALIGN;
+ if(parm_size)
+ len += (XRAN_SECTIONEXT_ALIGN - parm_size);
+
+ if(len != total_len) {
+ // TODO: fix this print_err("The size of extension 1 is not correct! [%d:%d]", len, total_len);
+ }
+
+ return (total_len);
+}
+
+int xran_parse_section_ext2(void *ext,
+ struct xran_sectionext2_info *extinfo)
+{
+ int len;
+ int total_len;
+ struct xran_cp_radioapp_section_ext2 *ext2;
+ uint8_t *data;
+ int parm_size;
+ uint32_t val;
+ int val_size;
+
+
+ ext2 = (struct xran_cp_radioapp_section_ext2 *)ext;
+ data = (uint8_t *)ext;
+ *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);
+
+ len = 0;
+ total_len = ext2->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
+
+ extinfo->bfAzPtWidth = ext2->bfAzPtWidth;
+ extinfo->bfZePtWidth = ext2->bfZePtWidth;
+ extinfo->bfAz3ddWidth = ext2->bfAz3ddWidth;
+ extinfo->bfZe3ddWidth = ext2->bfZe3ddWidth;
+
+ if(ext2->bfaCompResv0 || ext2->bfaCompResv1)
+ print_err("Incorrect reserved field - %d, %d", ext2->bfaCompResv0, ext2->bfaCompResv1);
+
+ data += parm_size;
+ len += parm_size;
+
+ val_size = (extinfo->bfAzPtWidth ? extinfo->bfAzPtWidth+1 : 0)
+ + (extinfo->bfZePtWidth ? extinfo->bfZePtWidth+1 : 0)
+ + (extinfo->bfAz3ddWidth ? extinfo->bfAz3ddWidth+1 : 0)
+ + (extinfo->bfZe3ddWidth ? extinfo->bfZe3ddWidth+ 1: 0);
+ if(val_size) {
+ val = rte_cpu_to_be_32(*(uint32_t *)data);
+ val >>= (32 - val_size);
+
+ if(extinfo->bfZe3ddWidth) {
+ extinfo->bfZe3dd = val & bitmask[extinfo->bfZe3ddWidth];
+ val >>= (extinfo->bfZe3ddWidth + 1);
+ }
+ if(extinfo->bfAz3ddWidth) {
+ extinfo->bfAz3dd = val & bitmask[extinfo->bfAz3ddWidth];
+ val >>= (extinfo->bfAz3ddWidth + 1);
+ }
+ if(extinfo->bfZePtWidth) {
+ extinfo->bfZePt = val & bitmask[extinfo->bfZePtWidth];
+ val >>= (extinfo->bfZePtWidth + 1);
+ }
+ if(extinfo->bfAzPtWidth) {
+ extinfo->bfAzPt = val & bitmask[extinfo->bfAzPtWidth];
+ val >>= (extinfo->bfAzPtWidth + 1);
+ }
+ }
+
+ parm_size = val_size/8;
+ if(val_size%8) parm_size += 1;
+
+ data += parm_size;
+ len += parm_size;
+
+ extinfo->bfAzSI = (*data >> 3) & 0x07;
+ extinfo->bfZeSI = *data & 0x07;
+
+ data++;
+ len++;
+
+ parm_size = len % XRAN_SECTIONEXT_ALIGN;
+ if(parm_size)
+ len += (XRAN_SECTIONEXT_ALIGN - parm_size);
+
+ if(len != total_len) {
+ print_err("The size of extension 2 is not correct! [%d:%d]", len, total_len);
+ }
+
+ return (total_len);
+
+}
+
+int xran_parse_section_ext4(void *ext,
+ struct xran_sectionext4_info *extinfo)
+{
+ int len;
+ struct xran_cp_radioapp_section_ext4 *ext4;
+ int total_len;
+
+
+ ext4 = (struct xran_cp_radioapp_section_ext4 *)ext;
+
+ *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t *)ext4);
+
+ len = 0;
+ total_len = ext4->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ extinfo->modCompScaler = ext4->modCompScaler;
+ extinfo->csf = ext4->csf;
+// extinfo->pad0;
+
+ len += sizeof(struct xran_cp_radioapp_section_ext4);
+ if(len != total_len) {
+ print_err("The size of extension 4 is not correct! [%d:%d]", len, total_len);
+ }
+
+ return (total_len);
+}
+
+int xran_parse_section_ext5(void *ext,
+ struct xran_sectionext5_info *extinfo)
+{
+ int len;
+ struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
+ struct xran_cp_radioapp_section_ext5 ext5;
+ int parm_size;
+ int total_len;
+ uint8_t *data;
+ uint16_t i;
+
+
+ ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)ext;
+ *(uint16_t *)ext_hdr = rte_cpu_to_be_16(*(uint16_t *)ext_hdr);
+
+ total_len = ext_hdr->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ // one set has 3.5 bytes, so enforcing double to do integer calculation
+ parm_size = ((total_len-sizeof(struct xran_cp_radioapp_section_ext_hdr))*2) / 7;
+
+ if(parm_size > XRAN_MAX_MODCOMP_ADDPARMS) {
+ print_err("Exceeds maximum number of parameters - %d", parm_size);
+ parm_size = XRAN_MAX_MODCOMP_ADDPARMS;
+ }
+
+ len = 0;
+ data = (uint8_t *)(ext_hdr + 1);
+
+ i = 0;
+ while(i < parm_size) {
+ // For odd number set, more data can be copied
+ *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)data));
+
+ extinfo->mc[i].mcScaleOffset = ext5.mcScaleOffset1;
+ extinfo->mc[i].csf = ext5.csf1;
+ extinfo->mc[i].mcScaleReMask = ext5.mcScaleReMask1;
+ i++;
+
+ extinfo->mc[i].mcScaleOffset = ext5.mcScaleOffset2;
+ extinfo->mc[i].csf = ext5.csf2;
+ extinfo->mc[i].mcScaleReMask = ext5.mcScaleReMask2;
+ i++;
+
+ data += sizeof(struct xran_cp_radioapp_section_ext5);
+ }
+
+ // check the values of last set
+ // due to alignment, it cannot be identified by the length that 3 or 4, 11 or 12 and etc
+ // don't check mcScaleOffset might not be zero (some part is out of zero-padding)
+ i--;
+ if(i < XRAN_MAX_MODCOMP_ADDPARMS) {
+ if(extinfo->mc[i].csf == 0 && extinfo->mc[i].mcScaleReMask == 0)
+ extinfo->num_sets = i;
+ else
+ extinfo->num_sets = i+1;
+ }else {
+ print_err("Maximum total number %d is not correct!", i);
+ }
+
+ return (total_len);
+}
+
+int xran_parse_section_extension(struct rte_mbuf *mbuf,
+ void *ext,
+ struct xran_section_gen_info *section)
+{
+ int total_len, len, numext;
+ uint8_t *ptr;
+ int flag_last;
+ int ext_type;
+ int i;
+
+ total_len = 0;
+ ptr = (uint8_t *)ext;
+
+ numext = 0;
+
+ flag_last = 1;
+ i = 0;
+ while(flag_last) {
+ /* check ef */
+ flag_last = (*ptr & 0x80);
+
+ ext_type = *ptr & 0x7f;
+ section->exData[numext].type = ext_type;
+ switch(ext_type) {
+ case XRAN_CP_SECTIONEXTCMD_1:
+ section->exData[numext].data = §ion->m_ext1[numext];
+ len = xran_parse_section_ext1(ptr, section->exData[numext].data);
+ section->exData[numext].len = len;
+ break;
+ case XRAN_CP_SECTIONEXTCMD_2:
+ section->exData[numext].data = §ion->m_ext2[numext];
+ len = xran_parse_section_ext2(ptr, section->exData[numext].data);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_4:
+ section->exData[numext].data = §ion->m_ext4[numext];
+ len = xran_parse_section_ext4(ptr, section->exData[numext].data);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_5:
+ section->exData[numext].data = §ion->m_ext5[numext];
+ len = xran_parse_section_ext5(ptr, section->exData[numext].data);
+ break;
+
+ case XRAN_CP_SECTIONEXTCMD_0:
+ case XRAN_CP_SECTIONEXTCMD_3:
+ default:
+ print_err("Extension %d is not supported!", ext_type);
+ len = 0;
+ }
+
+ section->exData[numext].len = len;
+ ptr += len; total_len += len;
+
+ i++;
+ if(++numext < XRAN_MAX_NUM_EXTENSIONS) continue;
+
+ /* exceeds maximum number of extensions */
+ break;
+ }
+
+ section->exDataSize = numext;
+
+ return (total_len);
+
+}
+