📄 lowl.c
字号:
/* 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 + -