⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lowl.c

📁 NUcleus plus 支持的文件系统。 是学习文件系统的很好参考资料。
💻 C
📖 第 1 页 / 共 5 页
字号:
            /* there are 128 entries per page */
            offset = (UINT16) (clno & 0x7f);
            ppage[offset] = *((UINT32 *)wrdbuf);
        }
    }
    else
    {
#ifdef DEBUG
        DEBUG_PRINT("pdr->fasize error %d  %s \r\n", __LINE__, __FILE__);
#endif
        return(NUF_INTERNAL);
    }
    return(NU_SUCCESS);
}


/************************************************************************
* FUNCTION                                                              
*                                                                       
*       pc_pfswap                                                       
*                                                                       
* DESCRIPTION                                                           
*                                                                       
*       Provide a cacheing mechanism for the file allocation table. We  
*       have a byte map table indicating the offset in our data cache   
*       for each block in the FAT. If the value at dat_map[block] is    
*       zero the block is not cached. We also maintain a bitmap of each 
*       block in the FAT. If the bit is set the corresponding block must
*       be flushed.                                                     
*                                                                       
* AUTHOR                                                                
*                                                                       
*      Takahiro Takahashi
*                                                                       
* INPUTS                                                                
*                                                                       
*       **pdata                             FAT buffer pointer          
*       *pdr                                Drive information           
*       index                               FAT entry number(cluster no)
*       for_write                           FAT update flag             
*                                                                       
* OUTPUTS                                                               
*                                                                       
*       NU_SUCCESS                          If service is successful.   
*       NUF_IO_ERROR                        Driver IO error.            
*       NUF_INTERNAL                        Nucleus FILE internal error.
*                                                                       
*************************************************************************/
STATUS pc_pfswap(UINT8 FAR **pdata, DDRIVE *pdr, UINT32 index, INT for_write)
{
FATSWAP     *pfs = &pdr->fat_swap_structure;
UINT32      newblock;
UINT32      block_offset_in_fat;
UINT32      i;
UINT8       uc;
UINT16      byte_offset;
UINT16      bit_offset;
UINT16      data_block_to_use;
UINT32      ltemp;
STATUS      ret_stat;


    if (pdr->fasize <= 4)
    {   /* FAT16 */
        /* Convert the index (in words) to block values 
           divide by 256 since there are 256 FAT entries per block */
        block_offset_in_fat = (UINT32) (index >> 8);
    }
    else
    {   /* FAT32 */
        /* Convert the index (in words) to block values 
           divide by 128 since there are 128 FAT entries per block */
        block_offset_in_fat = (UINT32) (index >> 7);
    }

    if (block_offset_in_fat >= pdr->secpfat) /* Check range */
        return(NUF_INTERNAL);

    /* check if the block is already mapped. 
           Notice we use block_0_is_valid as a flag denoting whether
           the first block in the fat is buffered. We did this because
           we want to use:
                data_map[block_offset_in_fat] == 0;
           Where data_map[] indicates the offset into our cache memory
           (in blocks) of the the cached buffer.  
           To indicate that the disk block is not cached. Since offset 0
           is a valid number we chose to preload the first disk block in the
           fat to location 0 in our buffer cache. After this has occured we
           set block_0_is_valid. Yuk, but effective.. 
    */
    /* Block 0 read.  */
    *pdata = (UINT8 FAR *)0;

    if ( (block_offset_in_fat < pfs->base_block ) ||
        (block_offset_in_fat >= pfs->base_block + pfs->data_map_size) )
    {
        /* The block is not in FAT cache */
        ret_stat = pc_pfflush(pdr);
        if (ret_stat != NU_SUCCESS)
            return(ret_stat);

        for (i = 0; (INT32)i < pfs->data_map_size; i++)
        {
            pfs->data_map[i] = 0;
        }
        pfs->block_0_is_valid = 0;
        pfs->base_block = block_offset_in_fat;
        block_offset_in_fat = 0;
        pfs->n_blocks_used = 0;
        pfs->n_to_swap = 1;
    }
    else
    {
        /* What is the index number in FAT cache */
        block_offset_in_fat -= pfs->base_block;

        if ( ((block_offset_in_fat == 0) && pfs->block_0_is_valid) || 
              (pfs->data_map[block_offset_in_fat] != 0) )
        {
            /* Already in our cache. set up a pointer to it */
            data_block_to_use = pfs->data_map[block_offset_in_fat];
            ltemp = (UINT32) data_block_to_use;
            *pdata = pfs->data_array + (ltemp << 9);
        }
    }

    if (*pdata == (UINT8 FAR *)0)
    {
        /* data_map > FAT cache size */
        if (pfs->n_blocks_total < pfs->data_map_size)
        {
            /* Not mapped, we have to read it in */
            if (pfs->n_blocks_used < pfs->n_blocks_total)
            {
            /* If we haven't reached steady state: use core until we 
               get there. */
                data_block_to_use = pfs->n_blocks_used;
                pfs->n_blocks_used += 1;
            }
            else
            {
                /* Flush the buffer
                    Later make this more selective by only flushing the block we
                    are swapping */
                ret_stat = pc_pfflush(pdr);
                if (ret_stat != NU_SUCCESS)
                    return(ret_stat);

                /* Select the block to swap out. Use a simple round-robin
                   selection algorithm: pfs->n_to_swap is the current 
                   target for swapping (block 0 is never swapped out)  */        
                if (!pfs->n_to_swap)
                    pfs->n_to_swap += 1;

                if (pfs->n_to_swap >= pfs->n_blocks_total)
                    pfs->n_to_swap = 1;
                data_block_to_use = 0;
                for (i = 0; (INT)i < pfs->data_map_size; i++)
                {
                    if (pfs->data_map[i] == pfs->n_to_swap)
                    {
                        /* swap this one out */
                       data_block_to_use = pfs->data_map[i];
                       pfs->data_map[i] = 0;
                       break;
                    }
                }
                pfs->n_to_swap += 1;

#ifdef DEBUG2
                if (!data_block_to_use)
                {
                    DEBUG_PRINT("pc_pfswap  FAT cache broken \r\n");
                }
#endif
            }
        }       /* END IF we had to swap */
        else
        {
            data_block_to_use = block_offset_in_fat;
        }

        /* Whether we are reusing a block or still coming up to speed.
           if the block is not currently in our pool we must mark the
           data block used and read it in */
        pfs->data_map[block_offset_in_fat] = data_block_to_use;

        newblock = pdr->fatblock + block_offset_in_fat + pfs->base_block;
        ltemp = (UINT32) data_block_to_use;
        *pdata = pfs->data_array + (ltemp << 9);

        /* READ */
        PC_DRIVE_IO_ENTER(pdr->driveno)
        if ( !pc_bdevsw[pdr->driveno].io_proc(pdr->driveno, newblock, *pdata, (UINT16) 1, YES) )
        {
            pfs->data_map[block_offset_in_fat] = 0;
            PC_DRIVE_IO_EXIT(pdr->driveno)
            return(NUF_IO_ERROR);
        }

        if (block_offset_in_fat == 0)
            pfs->block_0_is_valid = 1;

        PC_DRIVE_IO_EXIT(pdr->driveno)
    }        /* END IF the data needed reading in */

    /* If we should mark it dirty do so in the bit map */
    if (for_write)
    {
        byte_offset = (UINT16) (block_offset_in_fat >> 3);    /* divide by 8 */
        bit_offset = (UINT16) (block_offset_in_fat & 0x7);    /* mod 8 */
        uc = 1;
        uc <<= bit_offset;
        pfs->pdirty[byte_offset] |= uc;
    }
    return(NU_SUCCESS);
}


/************************************************************************
* FUNCTION                                                              
*                                                                       
*       pc_pfpword                                                      
*                                                                       
* DESCRIPTION                                                           
*                                                                       
*       Put a WORD value into the fat at index.                         
*                                                                       
* AUTHOR                                                                
*                                                                       
*       Takahiro Takahashi
*                                                                       
* INPUTS                                                                
*                                                                       
*       *pdr                                Drive information           
*       index                               FAT entry number            
*       *value                              FAT value pointer           
*                                                                       
* OUTPUTS                                                               
*                                                                       
*       NU_SUCCESS                          If service is successful.   
*       NUF_IO_ERROR                        Driver IO error.            
*       NUF_INTERNAL                        Nucleus FILE internal error.
*                                                                       
*************************************************************************/
STATUS pc_pfpword(DDRIVE *pdr, UINT16 index, UINT16 *pvalue)
{
UINT16 FAR  *ppage;
UINT16      offset;
STATUS      ret_stat;


    /* Make sure we have access to the page. Mark it for writing */
    ret_stat = pc_pfswap((UINT8 FAR **)&ppage, pdr, (UINT32)index, YES);

    if (ret_stat == NU_SUCCESS)
    {
        /* there are 256 entries per page */
        offset = (UINT16) (index & 0xff);
        ppage[offset] = *pvalue;
    }
    return(ret_stat);
}


/************************************************************************
* FUNCTION                                                              
*                                                                       
*       pc_pfgword                                                      
*                                                                       
* DESCRIPTION                                                           
*                                                                       
*       Get a WORD value from the fat at index.                         
*                                                                       
* AUTHOR                                                                
*                                                                       
*       Takahiro Takahashi
*                                                                       
* INPUTS                                                                
*                                                                       
*       *pdr                                Drive information           
*       index                               FAT entry number            
*       *value                              FAT value pointer           
*                                                                       
* OUTPUTS                                                               
*                                                                       
*       NU_SUCCESS                          If service is successful.   
*       NUF_IO_ERROR              

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -