📄 fsinit.c
字号:
/*-------------------------------------------------------------------*/
semPend(vol->sem, WAIT_FOREVER);
semPend(FlashSem, WAIT_FOREVER);
Flash = vol;
/*-------------------------------------------------------------------*/
/* For mounted volumes clear out all the internal structures. Start */
/* with the cache. */
/*-------------------------------------------------------------------*/
sect_sz = (int)Flash->sect_sz;
ReinitCache(&Flash->cache, sect_sz);
/*-------------------------------------------------------------------*/
/* Clear it's first files table, and if there are any left free them.*/
/*-------------------------------------------------------------------*/
FsReadCWD(&dummy, (void *)&curr_dir);
for (i = 2; i < FNUM_ENT; ++i)
{
Flash->files_tbl->tbl[i].type = FEMPTY;
/*-----------------------------------------------------------------*/
/* If the current directory is this entry, set it to first entry */
/* in the table, the root directory. */
/*-----------------------------------------------------------------*/
if (curr_dir == &Flash->files_tbl->tbl[i])
{
++Flash->files_tbl->tbl[0].entry.dir.cwds;
FsSaveCWD(dummy, (ui32)&Flash->files_tbl->tbl[0]);
}
}
Flash->files_tbl->free = FNUM_ENT - 2;
/*-------------------------------------------------------------------*/
/* Set the root dir's first entry to NULL. */
/*-------------------------------------------------------------------*/
Flash->files_tbl->tbl[0].entry.dir.first = NULL;
/*-------------------------------------------------------------------*/
/* Free all tables except for the first one. */
/*-------------------------------------------------------------------*/
for (temp_tbl = Flash->files_tbl->next_tbl; temp_tbl; )
{
/*-----------------------------------------------------------------*/
/* If the current directory is in this table set it to first entry */
/* for this volume, the root directory. */
/*-----------------------------------------------------------------*/
if (curr_dir >= &temp_tbl->tbl[0] &&
curr_dir < &temp_tbl->tbl[FNUM_ENT])
{
++Flash->files_tbl->tbl[0].entry.dir.cwds;
FsSaveCWD(dummy, (ui32)&Flash->files_tbl->tbl[0]);
}
prev_tbl = temp_tbl;
temp_tbl = temp_tbl->next_tbl;
free(prev_tbl);
}
Flash->files_tbl->next_tbl = NULL;
/*-------------------------------------------------------------------*/
/* Update file tables size. */
/*-------------------------------------------------------------------*/
Flash->tbls_size = (OFDIR_SZ + OFCOM_SZ + 1 +
strlen(Flash->files_tbl->tbl[0].entry.dir.name));
#if QUOTA_ENABLED
if (Flash->quota_enabled)
Flash->tbls_size += OFDIR_QUOTA_SZ;
#endif /* QUOTA_ENABLED */
/*-------------------------------------------------------------------*/
/* Set sect_tbl so that all valid blocks contain free sects. */
/*-------------------------------------------------------------------*/
for (block = 0; block < Flash->num_blocks; ++block)
{
/*-----------------------------------------------------------------*/
/* If valid block, mark all sectors as free. */
/*-----------------------------------------------------------------*/
if (!Flash->blocks[block].bad_block)
{
/*---------------------------------------------------------------*/
/* Get first sector in block and link it with last sector in */
/* previous block, if such sector exists. */
/*---------------------------------------------------------------*/
sect = block * Flash->block_sects + Flash->hdr_sects;
/*---------------------------------------------------------------*/
/* Since all data sects in block will be free, clear used count. */
/*---------------------------------------------------------------*/
Flash->blocks[block].used_sects = 0;
Flash->blocks[block].ctrl_block = FALSE;
for (i = Flash->hdr_sects; i < Flash->block_sects; ++i, ++sect)
{
/*-------------------------------------------------------------*/
/* If sector not free, mark it as dirty. */
/*-------------------------------------------------------------*/
if (Flash->sect_tbl[sect].prev != FFREE_SECT)
Flash->sect_tbl[sect].prev = FDRTY_SECT;
}
}
}
/*-------------------------------------------------------------------*/
/* There are no more used or ctrl sectors. */
/*-------------------------------------------------------------------*/
Flash->used_sects = 0;
Flash->frst_ctrl_sect = Flash->last_ctrl_sect = (ui32)-1;
Flash->free_ctrl_sect = (ui32)-1;
Flash->ctrl_sects = Flash->ctrl_size = 0;
/*-------------------------------------------------------------------*/
/* Set all other variables related to volume. */
/*-------------------------------------------------------------------*/
Flash->total_free = FNUM_ENT - 2;
Flash->total = FNUM_ENT;
#if QUOTA_ENABLED
/*-------------------------------------------------------------------*/
/* Reset root quota values if volume uses quotas. */
/*-------------------------------------------------------------------*/
if (Flash->quota_enabled)
{
FDIR_T *dir_t = &Flash->files_tbl->tbl[0].entry.dir;
dir_t->min_q = 0;
dir_t->free_below = 0;
dir_t->res_below = 0;
dir_t->used = strlen(dir_t->name) + 1 + OFDIR_SZ + OFDIR_QUOTA_SZ +
OFCOM_SZ;
dir_t->free = dir_t->max_q - dir_t->used;
}
#endif /* QUOTA_ENABLED */
/*-------------------------------------------------------------------*/
/* Do a sync now to save the state of the system. */
/*-------------------------------------------------------------------*/
if (FlashSync(DO_SYNC) != NULL)
{
semPost(FlashSem);
semPost(vol->sem);
return -1;
}
/*-------------------------------------------------------------------*/
/* Erase all sectors that need erasing. */
/*-------------------------------------------------------------------*/
if (FlashClean())
{
semPost(FlashSem);
semPost(vol->sem);
return -1;
}
/*-------------------------------------------------------------------*/
/* Release access to flash file system and this volume. */
/*-------------------------------------------------------------------*/
semPost(FlashSem);
semPost(vol->sem);
return 0;
}
/***********************************************************************/
/* next_free_block: Chooses the smallest wear count block */
/* */
/* Returns: Smallest block, or -1 if no such block exists */
/* */
/***********************************************************************/
static int next_free_block(void)
{
int block, nxt_free_blck = -1;
/*-------------------------------------------------------------------*/
/* Look through all blocks for one with smallest wear count. */
/*-------------------------------------------------------------------*/
for (block = 0; block < Flash->num_blocks; ++block)
if (!(Flash->blocks[block].bad_block ||
Flash->blocks[block].ctrl_block))
{
if (nxt_free_blck == -1 || Flash->blocks[block].wear_count <
Flash->blocks[nxt_free_blck].wear_count)
nxt_free_blck = block;
}
/*-------------------------------------------------------------------*/
/* If such a block found, temporarily mark its ctrl_block so it's */
/* not counted next time around. */
/*-------------------------------------------------------------------*/
if (nxt_free_blck != -1)
Flash->blocks[nxt_free_blck].ctrl_block = TRUE;
return nxt_free_blck;
}
/***********************************************************************/
/* set_first_free: Readjust free list and clean blocks that held old */
/* ctrl info */
/* */
/* Returns: 0 on success, -1 on error */
/* */
/***********************************************************************/
static int set_first_free(void)
{
int old_1st_ctrl_block = -1, old_2nd_ctrl_block = -1;
int frst_free_block = -1, block, status;
ui32 addr, hdr, sect, i;
FlashGlob *vol;
/*-------------------------------------------------------------------*/
/* Find the block with lowest wear count that has no ctrl info. */
/*-------------------------------------------------------------------*/
for (block = 0; block < Flash->num_blocks; ++block)
if (!(Flash->blocks[block].bad_block ||
Flash->blocks[block].ctrl_block))
{
if (frst_free_block == -1 || Flash->blocks[block].wear_count <
Flash->blocks[frst_free_block].wear_count)
frst_free_block = block;
}
/*-------------------------------------------------------------------*/
/* Mark all dirty/ctrl sectors as free. */
/*-------------------------------------------------------------------*/
for (block = 0; block < Flash->num_blocks; ++block)
{
if (!Flash->blocks[block].bad_block)
{
/*---------------------------------------------------------------*/
/* If this is a control block, remember it. */
/*---------------------------------------------------------------*/
if (Flash->blocks[block].ctrl_block)
{
Flash->blocks[block].ctrl_block = FALSE;
if (old_1st_ctrl_block == -1)
old_1st_ctrl_block = block;
else
{
PfAssert(old_2nd_ctrl_block == -1);
old_2nd_ctrl_block = block;
}
}
/*---------------------------------------------------------------*/
/* Bump up the wear count. */
/*---------------------------------------------------------------*/
Flash->blocks[block].wear_count += 1;
if (Flash->high_wear < Flash->blocks[block].wear_count)
Flash->high_wear = Flash->blocks[block].wear_count;
/*---------------------------------------------------------------*/
/* Make sure all sectors are free. */
/*---------------------------------------------------------------*/
sect = block * Flash->block_sects + Flash->hdr_sects;
for (i = Flash->hdr_sects; i < Flash->block_sects; ++i, ++sect)
{
if (Flash->sect_tbl[sect].prev != FFREE_SECT)
{
Flash->sect_tbl[sect].prev = FFREE_SECT;
++Flash->free_sects;
}
Flash->sect_tbl[sect].next = (ui16)(sect + 1);
}
}
}
/*-------------------------------------------------------------------*/
/* There are no more ctrl sectors. */
/*-------------------------------------------------------------------*/
Flash->frst_ctrl_sect = Flash->last_ctrl_sect = (ui32)-1;
Flash->ctrl_sects = Flash->ctrl_size = 0;
Flash->free_ctrl_sect = (ui32)-1;
/*-------------------------------------------------------------------*/
/* Readjust free sector list. When rearranging free list, place */
/* blocks in ascending order of wear count and set the next erasable */
/* set. */
/*-------------------------------------------------------------------*/
Flash->free_sect = frst_free_block * Flash->block_sects +
Flash->hdr_sects;
Flash->last_free_sect = (frst_free_block + 1) * Flash->block_sects - 1;
Flash->sect_tbl[Flash->last_free_sect].next = FLAST_SECT;
Flash->blocks[frst_free_block].ctrl_block = TRUE;
for (i = 1;; ++i)
{
/*-----------------------------------------------------------------*/
/* Choose next block to append to free list based on wear count. */
/*-----------------------------------------------------------------*/
block = next_free_block();
if (block == -1)
break;
/*-----------------------------------------------------------------*/
/* Append next block to free list. */
/*-----------------------------------------------------------------*/
Flash->sect_tbl[Flash->last_free_sect].next =
(ui16)(block * Flash->block_sects + Flash->hdr_sects);
Flash->last_free_sect = (block + 1) * Flash->block_sects - 1;
Flash->sect_tbl[Flash->last_free_sect].next = FLAST_SECT;
}
/*-------------------------------------------------------------------*/
/* Reset the erase set. */
/*-------------------------------------------------------------------*/
Flash->set_blocks = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -