+/* 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};
+
+/**
+ * @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)
+ 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;
+ }
+}
+