📄 fat_ioct.c
字号:
*
Description:
FS internal function. Store information about used/unused clusters
in a FS_DISKFREE_T data structure.
Parameters:
Idx - Index of device in the device information table
referred by FS__pDevInfo.
Unit - Unit number.
pDiskData - Pointer to a FS_DISKFREE_T data structure.
Return value:
==0 - Information is stored in pDiskData.
<0 - An error has occured.
*/
static int _FS_fat_GetTotalFree(int Idx, FS_u32 Unit, FS_DISKFREE_T *pDiskData) {
FS_u32 freeclust;
FS_u32 usedclust;
FS_u32 totclust;
FS_u32 fatentry;
FS_u32 fatsize;
FS_i32 fatoffs;
FS_i32 bytespersec;
FS_i32 cursec;
FS_i32 fatsec;
FS_i32 lastsec;
FS_i32 fatindex;
int fattype;
int err;
char *buffer;
unsigned char a;
unsigned char b;
#if (FS_FAT_NOFAT32==0)
unsigned char c;
unsigned char d;
#endif
if (!pDiskData) {
return -1; /* No pointer to a FS_DISKFREE_T structure */
}
buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
if (!buffer) {
return -1;
}
fattype = FS__fat_which_type(Idx, Unit);
#if (FS_FAT_NOFAT32!=0)
if (fattype == 2) {
FS__fat_free(buffer);
return -1;
}
#endif /* FS_FAT_NOFAT32!=0 */
fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
if (fatsize == 0) {
fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
}
bytespersec = (FS_i32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec;
/* Calculate total allocation units on disk */
totclust = FS__FAT_aBPBUnit[Idx][Unit].TotSec16;
if (!totclust) {
totclust = FS__FAT_aBPBUnit[Idx][Unit].TotSec32;
}
totclust -= FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt;
totclust -= 2*fatsize;
usedclust = FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt;
usedclust *= 0x20;
usedclust /= bytespersec;
totclust -= usedclust;
totclust /= FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
/* Scan FAT for free and used entries */
cursec = 0;
fatsec = 0;
lastsec = -1;
fatentry = 0xffffUL;
freeclust = 0;
usedclust = 0;
while (1) {
if (cursec >= (FS_i32)totclust) {
break; /* Last cluster reached */
}
if (fatsec >= (FS_i32)fatsize + FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt) {
break; /* End of FAT reached */
}
if (fattype == 1) {
fatindex = (cursec + 2) + ((cursec + 2) / 2); /* FAT12 */
}
else if (fattype == 2) {
fatindex = (cursec + 2) * 4; /* FAT32 */
}
else {
fatindex = (cursec + 2) * 2; /* FAT16 */
}
fatsec = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + (fatindex / bytespersec);
fatoffs = fatindex % bytespersec;
if (fatsec != lastsec) {
err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
if (err < 0) {
err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec, (void*)buffer);
if (err < 0) {
FS__fat_free(buffer);
return -1;
}
/* Try to repair original FAT sector with contents of copy */
FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
}
lastsec = fatsec;
}
if (fattype == 1) {
if (fatoffs == (bytespersec - 1)) {
a = buffer[fatoffs];
err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec+1, (void*)buffer);
if (err < 0) {
err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec + 1, (void*)buffer);
if (err < 0) {
FS__fat_free(buffer);
return -1;
}
/* Try to repair original FAT sector with contents of copy */
FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)buffer);
}
lastsec = fatsec + 1;
b = buffer[0];
}
else {
a = buffer[fatoffs];
b = buffer[fatoffs + 1];
}
if (cursec & 1) {
fatentry = ((a & 0xf0) >> 4 ) + 16 * b;
}
else {
fatentry = a + 256 * (b & 0x0f);
}
fatentry &= 0x0fff;
}
#if (FS_FAT_NOFAT32==0)
else if (fattype == 2) {
a = buffer[fatoffs];
b = buffer[fatoffs + 1];
c = buffer[fatoffs + 2];
d = buffer[fatoffs + 3];
fatentry = a + 0x100UL * b + 0x10000UL * c + 0x1000000UL * d;
fatentry &= 0x0fffffffUL;
}
#endif /* FS_FAT_NOFAT32==0 */
else {
a = buffer[fatoffs];
b = buffer[fatoffs + 1];
fatentry = a + 256 * b;
fatentry &= 0xffffUL;
}
cursec++;
if (fatentry == 0) {
freeclust++;
}
else {
usedclust++;
}
}
FS__fat_free(buffer);
pDiskData->total_clusters = totclust;
pDiskData->avail_clusters = freeclust;
pDiskData->sectors_per_cluster = FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
pDiskData->bytes_per_sector = (FS_u16)bytespersec;
return 0;
}
#endif /* FS_FAT_DISKINFO */
/*********************************************************************
*
* Global functions
*
**********************************************************************
*/
/*********************************************************************
*
* FS__fat_ioctl
*
Description:
FS internal function. Execute device command. The FAT layer checks
first, if it has to process the command (e.g. format). Any other
command is passed to the device driver.
Parameters:
Idx - Index of device in the device information table
referred by FS__pDevInfo.
Unit - Unit number.
Cmd - Command to be executed.
Aux - Parameter depending on command.
pBuffer - Pointer to a buffer used for the command.
Return value:
Command specific. In general a negative value means an error.
*/
int FS__fat_ioctl(int Idx, FS_u32 Unit, FS_i32 Cmd, FS_i32 Aux, void *pBuffer) {
int x;
#if ((FS_SUPPORT_SEC_ACCESS) || (FS_FAT_NOFORMAT==0))
int i;
#endif
#if (FS_FAT_NOFORMAT==0)
int j;
#endif
FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_INC_BUSYCNT, 0, (void*)0); /* Turn on busy signal */
#if (FS_FAT_NOFORMAT==0)
if (Cmd == FS_CMD_FORMAT_MEDIA) {
j = 0;
while (1) {
if (j >= FS_KNOWNMEDIA_NUM) {
break; /* Not a known media */
}
if (_FS_wd_format_media_table[j].media_id == Aux) {
break; /* Media found in the list */
}
j++;
} //find the right media
if (j >= FS_KNOWNMEDIA_NUM) { //can't find the right media
FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0); /* Turn off busy signal */
return -1;
}
i = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit); //get status of device, if ok return 1
if (i >= 0) {
x = _FS_fat_format(FS__pDevInfo[Idx].devdriver,
Unit,
_FS_wd_format_media_table[j].secperclus,
_FS_wd_format_media_table[j].rootentcnt,
_FS_wd_format_media_table[j].totsec16,
_FS_wd_format_media_table[j].totsec32,
_FS_wd_format_media_table[j].media,
_FS_wd_format_media_table[j].fatsz16,
0,
_FS_wd_format_media_table[j].secpertrk,
_FS_wd_format_media_table[j].numheads,
_FS_wd_format_media_table[j].hiddsec,
_FS_wd_format_media_table[j].fsystype);
i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_FLUSH_CACHE, 0, (void*)0);
if (i < 0) {
x = i;
}
else {
/* Invalidate BPB */
for (i = 0; i < (int)FS__maxdev; i++) {
for (j = 0; j < (int)FS__fat_maxunit; j++) {
FS__FAT_aBPBUnit[i][j].Signature = 0x0000;
}
}
}
}
else {
FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0); /* Turn off busy signal */
return -1;
}
}
else if (Cmd == FS_CMD_FORMAT_AUTO) {
i = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit);
if (i >= 0) {
x = _FS_FAT_AutoFormat(Idx, Unit);
i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_FLUSH_CACHE, 0, (void*)0);
if (i < 0) {
x = i;
}
}
else {
x = -1;
}
}
#else /* FS_FAT_NOFORMAT==0 */
if (Cmd == FS_CMD_FORMAT_MEDIA) {
x = -1; /* Format command is not supported */
}
#endif /* FS_FAT_NOFORMAT==0 */
#if FS_FAT_DISKINFO
else if (Cmd == FS_CMD_GET_DISKFREE) {
i = FS__fat_checkunit(Idx, Unit);
if (i > 0) {
x = _FS_fat_GetTotalFree(Idx, Unit, (FS_DISKFREE_T*)pBuffer);
i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_FLUSH_CACHE, 0, (void*)0);
if (i < 0) {
x = i;
}
}
else {
x = -1;
}
}
#else /* FS_FAT_DISKINFO==0 */
else if (Cmd == FS_CMD_GET_DISKFREE) {
x = -1; /* Diskinfo command not supported */
}
#endif /* FS_FAT_DISKINFO */
#if FS_SUPPORT_SEC_ACCESS
else if ((Cmd == FS_CMD_READ_SECTOR) || (Cmd == FS_CMD_WRITE_SECTOR)) {
if (!pBuffer) {
FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);
return -1;
}
i = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit);
if (i >= 0) {
if (Cmd == FS_CMD_READ_SECTOR) {
x = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, Aux, pBuffer);
}
else {
x = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, Aux, pBuffer);
}
}
else {
x = -1;
}
}
#else /* FS_SUPPORT_SEC_ACCESS */
else if ((Cmd == FS_CMD_READ_SECTOR) || (Cmd == FS_CMD_WRITE_SECTOR)) {
FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);
return -1;
}
#endif /* FS_SUPPORT_SEC_ACCESS */
else {
/* Maybe command for driver */
x = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, Cmd, Aux, (void*)pBuffer);
}
FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0); /* Turn off busy signal */
return x;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -