static void SeekCoord()

in FreeRTOS-Plus/Source/Reliance-Edge/core/driver/inodedata.c [987:1130]


static void SeekCoord(
    CINODE     *pInode,
    uint32_t    ulBlock)
{
    if(!CINODE_IS_MOUNTED(pInode) || (ulBlock >= INODE_DATA_BLOCKS))
    {
        REDERROR();
    }
    else if((pInode->ulLogicalBlock != ulBlock) || !pInode->fCoordInited)
    {
        RedInodePutData(pInode);
        pInode->ulLogicalBlock = ulBlock;

      #if REDCONF_DIRECT_POINTERS > 0U
      #if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
        if(ulBlock < REDCONF_DIRECT_POINTERS)
      #endif
        {
          #if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
            RedInodePutCoord(pInode);
          #endif

            pInode->uInodeEntry = (uint16_t)ulBlock;
            pInode->ulDataBlock = pInode->pInodeBuf->aulEntries[pInode->uInodeEntry];

          #if DINDIR_POINTERS > 0U
            pInode->uDindirEntry = COORD_ENTRY_INVALID;
          #endif
          #if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
            pInode->uIndirEntry = COORD_ENTRY_INVALID;
          #endif
        }
      #if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
        else
      #endif
      #endif
      #if REDCONF_INDIRECT_POINTERS > 0U
      #if REDCONF_INDIRECT_POINTERS < INODE_ENTRIES
        if(ulBlock < (INODE_INDIR_BLOCKS + REDCONF_DIRECT_POINTERS))
      #endif
        {
            uint32_t ulIndirRangeOffset = ulBlock - REDCONF_DIRECT_POINTERS;
            uint16_t uInodeEntry = (uint16_t)((ulIndirRangeOffset / INDIR_ENTRIES) + REDCONF_DIRECT_POINTERS);
            uint16_t uIndirEntry = (uint16_t)(ulIndirRangeOffset % INDIR_ENTRIES);

          #if DINDIR_POINTERS > 0U
            RedInodePutDindir(pInode);
          #endif

            /*  If the inode entry is not changing, then the previous indirect
                is still the correct one.  Otherwise, the old indirect will be
                released and the new one will be read later.
            */
            if((pInode->uInodeEntry != uInodeEntry) || !pInode->fCoordInited)
            {
                RedInodePutIndir(pInode);

                pInode->uInodeEntry = uInodeEntry;

                pInode->ulIndirBlock = pInode->pInodeBuf->aulEntries[pInode->uInodeEntry];
            }

          #if DINDIR_POINTERS > 0U
            pInode->uDindirEntry = COORD_ENTRY_INVALID;
          #endif
            pInode->uIndirEntry = uIndirEntry;

            /*  At this point, the following pInode members are needed but not
                yet populated:

                - pIndir
                - ulDataBlock
            */
        }
      #if DINDIR_POINTERS > 0U
        else
      #endif
      #endif
      #if DINDIR_POINTERS > 0U
        {
            uint32_t ulDindirRangeOffset = (ulBlock - REDCONF_DIRECT_POINTERS) - INODE_INDIR_BLOCKS;
            uint16_t uInodeEntry = (uint16_t)((ulDindirRangeOffset / DINDIR_DATA_BLOCKS) + REDCONF_DIRECT_POINTERS + REDCONF_INDIRECT_POINTERS);
            uint32_t ulDindirNodeOffset = ulDindirRangeOffset % DINDIR_DATA_BLOCKS;
            uint16_t uDindirEntry = (uint16_t)(ulDindirNodeOffset / INDIR_ENTRIES);
            uint16_t uIndirEntry = (uint16_t)(ulDindirNodeOffset % INDIR_ENTRIES);

            /*  If the inode entry is not changing, then the previous double
                indirect is still the correct one.  Otherwise, the old double
                indirect will be released and the new one will be read later.
            */
            if((pInode->uInodeEntry != uInodeEntry) || !pInode->fCoordInited)
            {
                RedInodePutIndir(pInode);
                RedInodePutDindir(pInode);

                pInode->uInodeEntry = uInodeEntry;

                pInode->ulDindirBlock = pInode->pInodeBuf->aulEntries[pInode->uInodeEntry];
            }
            /*  If neither the inode entry nor double indirect entry are
                changing, then the previous indirect is still the correct one.
                Otherwise, it old indirect will be released and the new one will
                be read later.
            */
            else if(pInode->uDindirEntry != uDindirEntry)
            {
                RedInodePutIndir(pInode);
            }
            else
            {
                /*  Data buffer has already been put, nothing to do.
                */
            }

            pInode->uDindirEntry = uDindirEntry;
            pInode->uIndirEntry = uIndirEntry;

            /*  At this point, the following pInode members are needed but not
                yet populated:

                - pDindir
                - pIndir
                - ulIndirBlock
                - ulDataBlock
            */
        }
      #elif (REDCONF_DIRECT_POINTERS > 0U) && (REDCONF_INDIRECT_POINTERS > 0U)
        else
        {
            /*  There are no double indirects, so the block should have been in
                the direct or indirect range.
            */
            REDERROR();
        }
      #endif

        pInode->fCoordInited = true;
    }
    else
    {
        /*  Seeking to the current position, nothing to do.
        */
    }
}