+/*CQI Table From Spec 38.214 Table 5.2.2.1-2
+ * {Modulation Scheme, CodeRate, Efficiency(bits per symbol)}
+ * Modulation Scheme is numbered based on bit rate as follows
+ * QPSK = 2, 16QAM = 4, 64QAM = 6
+ * */
+unsigned long cqiTable1[MAX_NUM_CQI_IDX][3] = {
+{ 0, 0, 0}, /*index 0*/
+{ 2, 78, 0.1523}, /*index 1*/
+{ 2, 120, 0.2344}, /*index 2*/
+{ 2, 193, 0.3770}, /*index 3*/
+{ 2, 308, 0.6016}, /*index 4*/
+{ 2, 449, 0.8770}, /*index 5*/
+{ 2, 602, 1.1758}, /*index 6*/
+{ 4, 378, 1.4766}, /*index 7*/
+{ 4, 490, 1.9141}, /*index 8*/
+{ 4, 616, 2.4063}, /*index 9*/
+{ 6, 466, 2.7305}, /*index 10*/
+{ 6, 567, 3.3223}, /*index 11*/
+{ 6, 666, 3.9023}, /*index 12*/
+{ 6, 772, 4.5234}, /*index 13*/
+{ 6, 873, 5.1152}, /*index 14*/
+{ 6, 948, 5.5547}, /*index 15*/
+};
+
+/*As per Spec 38.211 Table 7.3.2.1-1, using number of CCE per AggLevel
+ * Num of RE for Agg Level = numCCEPerAggLevel * (6 REG) * (12 Subcarriers)
+ */
+uint16_t totalRE_PerAggLevel[MAX_NUM_AGG_LVL]= {72, 144, 288, 576, 1152};
+
+
+/* Minimum Msg3 scheduling time should be calculated based on N1+N2+NTAmax+0.5
+ * ms formula.
+ * Refer spec 38.213 section 8.3.
+ * Harcoding the minimum msg3 scheduling for now */
+uint8_t minMsg3SchTime[MAX_NUM_MU] = {6, 6, 6, 6};
+
+uint8_t defaultUlAckTbl[DEFAULT_UL_ACK_LIST_COUNT]= {1, 2, 3 , 4, 5, 6, 7, 8};
+
+uint8_t schCmnDlRvTbl[4] = {0, 2, 3, 1};
+/**
+ * @brief Function to find first DMRS symbol in PDSCH
+ *
+ * @details
+ *
+ * Function: findDmrsStartSymbol
+ *
+ * This function finds first DMRS symbol using DMRS symbol
+ * position bitmap.
+ *
+ * @param[in] DMRS symbol position bitmap
+ * @return Success : First DRMS symbol
+ * Failure : MAX_SYMB_PER_SLOT
+ **/
+uint8_t findDmrsStartSymbol(uint16_t dlDmrsSymbBitMap)
+{
+ uint8_t position = 0;
+ uint16_t mask = 1;
+
+ while(position < MAX_SYMB_PER_SLOT)
+ {
+ if(dlDmrsSymbBitMap & mask)
+ break;
+ mask = mask << 1;
+ position++;
+ }
+ return position;
+}
+
+/**
+ * @brief Function to add a node to a linked list
+ *
+ * @details
+ *
+ * Function: addNodeToLList
+ *
+ * This function adds a new node to the linked list
+ *
+ * @param[in] Pointer to the list
+ * Pointer to node to be added
+ * Pointer to current node
+ * @return ROK
+ * RFAILED
+ **/
+uint8_t addNodeToLList(CmLListCp *llist, void *blockToAdd, CmLList *currNode)
+{
+ CmLList *newNode;
+
+ SCH_ALLOC(newNode, sizeof(CmLList));
+ if(newNode)
+ {
+ newNode->node = (PTR)blockToAdd;
+
+ if(currNode == NULLP)
+ cmLListAdd2Tail(llist, newNode);
+ else
+ {
+ llist->crnt = currNode;
+ cmLListInsAfterCrnt(llist, newNode);
+ }
+ return ROK;
+ }
+ return RFAILED;
+}
+
+/**
+ * @brief Function to delete a node from linked list
+ *
+ * @details
+ *
+ * Function: deleteNodeFromLList
+ *
+ * This function deletes a node from the linked list
+ *
+ * @param[in] Pointer to the list
+ * Pointer to node to be deleted
+ * @return Pointer to the deleted node
+ **/
+uint8_t deleteNodeFromLList(CmLListCp *llist, CmLList *node)
+{
+ node = cmLListDelFrm(llist, node);
+ SCH_FREE(node, sizeof(CmLList));
+
+ return ROK;
+}
+
+/**
+ * @brief Checks if requested PRBs are free
+ *
+ * @details
+ *
+ * Function: isPrbAvailable
+ *
+ * This functions loops through all free PRB blocks and
+ * checks if request PRB block is available for allocation
+ *
+ * @param[in] List of free PRB blocks
+ * First PRB requested
+ * Total number of PRB requested
+ *
+ * @return Returns Pointer to free block
+ * NULL
+ **/
+CmLList* isPrbAvailable(CmLListCp *freePrbBlockList, uint16_t startPrb, uint16_t numPrb)
+{
+ uint16_t endPrb = 0;
+ CmLList *node = NULLP;
+ FreePrbBlock *freeBlock = NULLP;
+
+ endPrb = startPrb + numPrb - 1;
+
+ /* Iterate through all blocks of free PRB to check if requested PRBs can be assigned */
+ node = freePrbBlockList->first;
+ while(node)
+ {
+ freeBlock = (FreePrbBlock *)node->node;
+
+ /* Check if requested number of blocks can be allocated from the current block */
+ if(freeBlock->numFreePrb < numPrb)
+ {
+ DU_LOG("\nINFO --> SCH: In isPrbAvailable, numFreePrb:%d is less than reqPrb:%d", freeBlock->numFreePrb, numPrb);
+ node = node->next;
+ continue;
+ }
+
+ /* Check if requested PRBs belong within the range of current free block */
+ if(((startPrb >= freeBlock->startPrb) && (startPrb <= freeBlock->endPrb)) && \
+ ((endPrb >= freeBlock->startPrb) && (endPrb <= freeBlock->endPrb)))
+ {
+ return node;
+ }
+
+ /* If current block is unable to provide resources, check the next block */
+ node = node->next;
+ }
+ return NULLP;
+}
+
+/**
+ * @brief Function to update free PRB list
+ *
+ * @details
+ *
+ * Function: removeAllocatedPrbFromFreePrbList
+ *
+ * This function removes the allocated PRBs from the
+ * list of free PRBs
+ *
+ * @param[in] Pointer to the list
+ * Pointer to node from which PRB was allocated
+ * Start PRB allocated
+ * Number of PRBs allocated
+ * @return void
+ **/
+void removeAllocatedPrbFromFreePrbList(CmLListCp *freePrbBlockList, CmLList *node, uint16_t startPrb, uint16_t numPrb)
+{
+ uint16_t endPrb;
+ FreePrbBlock *newBlock = NULLP;
+ FreePrbBlock *freeBlock = (FreePrbBlock *)node->node;
+
+ if(!node)
+ return;
+
+ endPrb = startPrb + numPrb -1;
+
+ /* If the whole block is allocated, remove it from linked list */
+ if(freeBlock->numFreePrb == numPrb)
+ {
+ if(deleteNodeFromLList(freePrbBlockList, node) == ROK)
+ SCH_FREE(freeBlock, sizeof(FreePrbBlock));
+ }
+
+ /* If PRB is allocated from start of free block, move the start of free block
+ * after last alloctaed PRB */
+ else if(freeBlock->startPrb == startPrb)
+ {
+ freeBlock->startPrb = endPrb+1;
+ freeBlock->numFreePrb = freeBlock->endPrb - freeBlock->startPrb +1;
+ }
+
+ /* If PRB is allocated from end of free block, move the end of free block
+ * before the first allocated PRB */
+ else if(freeBlock->endPrb == endPrb)
+ {
+ freeBlock->endPrb = startPrb-1;
+ freeBlock->numFreePrb = freeBlock->endPrb - freeBlock->startPrb +1;
+ }
+
+ /* If PRBs are allocated somewhere in between the free block, split it into 2
+ * nodes. Fist node contains free PRBs after the allocated PRBs. Second node
+ * contains free PRBs present before the allocated PRBs */
+ else
+ {
+ /* Block 2 */
+ SCH_ALLOC(newBlock, sizeof(FreePrbBlock));
+ if(newBlock)
+ {
+ newBlock->startPrb = freeBlock->startPrb;
+ newBlock->endPrb = startPrb-1;
+ newBlock->numFreePrb = newBlock->endPrb - newBlock->startPrb +1;
+ addNodeToLList(freePrbBlockList, newBlock, node);
+ }
+
+ /* Block 1 */
+ freeBlock->startPrb = endPrb+1;
+ freeBlock->numFreePrb = freeBlock->endPrb - freeBlock->startPrb +1;
+ }
+}
+