fatfs/src/ff.c
static FRESULT remove_chain (	/* FR_OK(0):succeeded, !=0:error */
	FFOBJID* obj,		/* Corresponding object */
	DWORD clst,			/* Cluster to remove a chain from */
	DWORD pclst			/* Previous cluster of clst (0 if entire chain) */
)
{
	FRESULT res = FR_OK;
	DWORD nxt;
	FATFS *fs = obj->fs;
#if FF_FS_EXFAT || FF_USE_TRIM
	DWORD scl = clst, ecl = clst;
#endif
#if FF_USE_TRIM
	DWORD rt[2];
#endif

	if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR;	/* Check if in valid range */

	/* Mark the previous cluster 'EOC' on the FAT if it exists */
	if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) {
		res = put_fat(fs, pclst, 0xFFFFFFFF);
		if (res != FR_OK) return res;
	}

	/* Remove the chain */
	do {
		nxt = get_fat(obj, clst);			/* Get cluster status */
		if (nxt == 0) break;				/* Empty cluster? */
		if (nxt == 1) return FR_INT_ERR;	/* Internal error? */
		if (nxt == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error? */
		if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
			res = put_fat(fs, clst, 0);		/* Mark the cluster 'free' on the FAT */
			if (res != FR_OK) return res;
		}
		if (fs->free_clst < fs->n_fatent - 2) {	/* Update FSINFO */
			fs->free_clst++;
			fs->fsi_flag |= 1;
		}
#if FF_FS_EXFAT || FF_USE_TRIM
		if (ecl + 1 == nxt) {	/* Is next cluster contiguous? */
			ecl = nxt;
		} else {				/* End of contiguous cluster block */
#if FF_FS_EXFAT
			if (fs->fs_type == FS_EXFAT) {
				res = change_bitmap(fs, scl, ecl - scl + 1, 0);	/* Mark the cluster block 'free' on the bitmap */
				if (res != FR_OK) return res;
			}
#endif
#if FF_USE_TRIM
			rt[0] = clst2sect(fs, scl);					/* Start of data area freed */
			rt[1] = clst2sect(fs, ecl) + fs->csize - 1;	/* End of data area freed */
			disk_ioctl(fs->pdrv, CTRL_TRIM, rt);		/* Inform device the data in the block is no longer needed */
#endif
			scl = ecl = nxt;
		}
#endif
		clst = nxt;					/* Next cluster */
	} while (clst < fs->n_fatent);	/* Repeat while not the last link */

#if FF_FS_EXFAT
	/* Some post processes for chain status */
	if (fs->fs_type == FS_EXFAT) {
		if (pclst == 0) {	/* Has the entire chain been removed? */
			obj->stat = 0;		/* Change the chain status 'initial' */
		} else {
			if (obj->stat == 0) {	/* Is it a fragmented chain from the beginning of this session? */
				clst = obj->sclust;		/* Follow the chain to check if it gets contiguous */
				while (clst != pclst) {
					nxt = get_fat(obj, clst);
					if (nxt < 2) return FR_INT_ERR;
					if (nxt == 0xFFFFFFFF) return FR_DISK_ERR;
					if (nxt != clst + 1) break;	/* Not contiguous? */
					clst++;
				}
				if (clst == pclst) {	/* Has the chain got contiguous again? */
					obj->stat = 2;		/* Change the chain status 'contiguous' */
				}
			} else {
				if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) {	/* Was the chain fragmented in this session and got contiguous again? */
					obj->stat = 2;	/* Change the chain status 'contiguous' */
				}
			}
		}
	}
#endif
	return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* FAT handling - Remove a cluster chain                                 */
/*-----------------------------------------------------------------------*/
FAT handling - Remove a cluster chain
FAT handling - Remove a cluster chain
static FRESULT remove_chain (	
	FFOBJID* obj,		
	DWORD clst,			
	DWORD pclst			
)
{
	FRESULT res = FR_OK;
	DWORD nxt;
	FATFS *fs = obj->fs;
#if FF_FS_EXFAT || FF_USE_TRIM
	DWORD scl = clst, ecl = clst;
#endif
#if FF_USE_TRIM
	DWORD rt[2];
#endif
	if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR;	
	if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) {
		res = put_fat(fs, pclst, 0xFFFFFFFF);
		if (res != FR_OK) return res;
	}
	do {
		nxt = get_fat(obj, clst);			
		if (nxt == 0) break;				
		if (nxt == 1) return FR_INT_ERR;	
		if (nxt == 0xFFFFFFFF) return FR_DISK_ERR;	
		if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
			res = put_fat(fs, clst, 0);		
			if (res != FR_OK) return res;
		}
		if (fs->free_clst < fs->n_fatent - 2) {	
			fs->free_clst++;
			fs->fsi_flag |= 1;
		}
#if FF_FS_EXFAT || FF_USE_TRIM
		if (ecl + 1 == nxt) {	
			ecl = nxt;
		} else {				
#if FF_FS_EXFAT
			if (fs->fs_type == FS_EXFAT) {
				res = change_bitmap(fs, scl, ecl - scl + 1, 0);	
				if (res != FR_OK) return res;
			}
#endif
#if FF_USE_TRIM
			rt[0] = clst2sect(fs, scl);					
			rt[1] = clst2sect(fs, ecl) + fs->csize - 1;	
			disk_ioctl(fs->pdrv, CTRL_TRIM, rt);		
#endif
			scl = ecl = nxt;
		}
#endif
		clst = nxt;					
	} while (clst < fs->n_fatent);	
#if FF_FS_EXFAT
	if (fs->fs_type == FS_EXFAT) {
		if (pclst == 0) {	
			obj->stat = 0;		
		} else {
			if (obj->stat == 0) {	
				clst = obj->sclust;		
				while (clst != pclst) {
					nxt = get_fat(obj, clst);
					if (nxt < 2) return FR_INT_ERR;
					if (nxt == 0xFFFFFFFF) return FR_DISK_ERR;
					if (nxt != clst + 1) break;	
					clst++;
				}
				if (clst == pclst) {	
					obj->stat = 2;		
				}
			} else {
				if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) {	
					obj->stat = 2;	
				}
			}
		}
	}
#endif
	return FR_OK;
}
static FRESULT remove_chain ( FFOBJID * obj , DWORD clst , DWORD pclst ) { FRESULT res = FR_OK ; DWORD nxt ; FATFS * fs = obj -> fs ; #if FF_FS_EXFAT || FF_USE_TRIM DWORD scl = clst , ecl = clst ; #endif #if FF_USE_TRIM DWORD rt [ 2 ] ; #endif if ( clst < 2 || clst >= fs -> n_fatent ) return FR_INT_ERR ; if ( pclst != 0 && ( ! FF_FS_EXFAT || fs -> fs_type != FS_EXFAT || obj -> stat != 2 ) ) { res = put_fat ( fs , pclst , 0xFFFFFFFF ) ; if ( res != FR_OK ) return res ; } do { nxt = get_fat ( obj , clst ) ; if ( nxt == 0 ) break ; if ( nxt == 1 ) return FR_INT_ERR ; if ( nxt == 0xFFFFFFFF ) return FR_DISK_ERR ; if ( ! FF_FS_EXFAT || fs -> fs_type != FS_EXFAT ) { res = put_fat ( fs , clst , 0 ) ; if ( res != FR_OK ) return res ; } if ( fs -> free_clst < fs -> n_fatent - 2 ) { fs -> free_clst ++ ; fs -> fsi_flag |= 1 ; } #if FF_FS_EXFAT || FF_USE_TRIM if ( ecl + 1 == nxt ) { ecl = nxt ; } else { #if FF_FS_EXFAT if ( fs -> fs_type == FS_EXFAT ) { res = change_bitmap ( fs , scl , ecl - scl + 1 , 0 ) ; if ( res != FR_OK ) return res ; } #endif #if FF_USE_TRIM rt [ 0 ] = clst2sect ( fs , scl ) ; rt [ 1 ] = clst2sect ( fs , ecl ) + fs -> csize - 1 ; disk_ioctl ( fs -> pdrv , CTRL_TRIM , rt ) ; #endif scl = ecl = nxt ; } #endif clst = nxt ; } while ( clst < fs -> n_fatent ) ; #if FF_FS_EXFAT if ( fs -> fs_type == FS_EXFAT ) { if ( pclst == 0 ) { obj -> stat = 0 ; } else { if ( obj -> stat == 0 ) { clst = obj -> sclust ; while ( clst != pclst ) { nxt = get_fat ( obj , clst ) ; if ( nxt < 2 ) return FR_INT_ERR ; if ( nxt == 0xFFFFFFFF ) return FR_DISK_ERR ; if ( nxt != clst + 1 ) break ; clst ++ ; } if ( clst == pclst ) { obj -> stat = 2 ; } } else { if ( obj -> stat == 3 && pclst >= obj -> sclust && pclst <= obj -> sclust + obj -> n_cont ) { obj -> stat = 2 ; } } } } #endif return FR_OK ; }
FAT handling - Remove a cluster chain
FAT handling - Remove a cluster chain
/* FR_OK(0):succeeded, !=0:error */ /* Corresponding object */ /* Cluster to remove a chain from */ /* Previous cluster of clst (0 if entire chain) */ /* Check if in valid range */ /* Mark the previous cluster 'EOC' on the FAT if it exists */ /* Remove the chain */ /* Get cluster status */ /* Empty cluster? */ /* Internal error? */ /* Disk error? */ /* Mark the cluster 'free' on the FAT */ /* Update FSINFO */ /* Is next cluster contiguous? */ /* End of contiguous cluster block */ /* Mark the cluster block 'free' on the bitmap */ /* Start of data area freed */ /* End of data area freed */ /* Inform device the data in the block is no longer needed */ /* Next cluster */ /* Repeat while not the last link */ /* Some post processes for chain status */ /* Has the entire chain been removed? */ /* Change the chain status 'initial' */ /* Is it a fragmented chain from the beginning of this session? */ /* Follow the chain to check if it gets contiguous */ /* Not contiguous? */ /* Has the chain got contiguous again? */ /* Change the chain status 'contiguous' */ /* Was the chain fragmented in this session and got contiguous again? */ /* Change the chain status 'contiguous' */