📄 device.c
字号:
{
next = bad_fat_entries[i];
if (next < 2) /* Free clusters are ignored */
continue;
while (n < num)
{
if ( *qfat == 0 ) /* find a free cluster */
{ /* The free cluster is the first one found in the EB */
if (mflag == 0)
{ /* Load the data of the EB */
rdbuf = (UINT8 *)MALLOC(en<<9);
if (rdbuf == NULL)
{
FREE(bad_fat_entries);
FREE(rep_fat_entries);
return 0;/*error*/
}
if (!pdev->io_proc(driveno, neweb, rdbuf, en, YES))
{
/* If error, the EB is ignored and it jumps to
* the next EB. The error will be handled when
* the bad EB is accessed next time. */
FREE(rdbuf); rdbuf = NULL;
/* Find next EB */
pfat -= num; neweb-=en; qfat = pfat; n = 0;
/* If there are no FREE clusters, break out of the whole loop */
if (neweb < pdr->firstclblock)
break;
continue;
}
}
/* Copy the cluster's data into the new place */
m = pdr->secpalloc << 9;
memcpy(rdbuf+(n*m), (char *)buffer+(i*m), m);
/*
* Modify the FAT and INVERSE FAT.
*/
/* The new cluster's number is saved in the bad_fat_entries[] */
m = (neweb - pdr->firstclblock)/pdr->secpalloc + n + 2;
rep_fat_entries[i] = m;
/* The next cluster's number(may be bad) is saved in the new cluster */
if ( next < clsno || next >= clsno + num )
{ /* If the next cluster is not in the same bad EB, put the next cluster's
* number into the new cluster, and set its previous pointer (saved
* in INVERSE FAT) point to the new cluster. */
SWAP16((UINT16*)qfat, (UINT16*)&next);
SWAP16((UINT16*)&vfat[next], (UINT16*)&m);
}
else if (next < clsno + i )
{ /* If the next cluster is in the same bad EB and is in front of the bad
* cluster, the replacement's number of the next cluster which was
* saved in the bad_fat_entries[] will be put into the new cluster. */
tmp = rep_fat_entries[next - clsno];
SWAP16((UINT16*)qfat, (UINT16*)&tmp);
SWAP16((UINT16*)&vfat[tmp], (UINT16*)&m);
}
else
{ /* If the next cluster is in the same bad EB and is behind the bad
* cluster, the next cluster's previous pointer is modified and set to
* the value of the new cluster. */
SWAP16((UINT16*)&vfat[next], (UINT16*)&m);
}
/* If the bad cluster has a valid previous brother, modify it. */
tmp = vfat[clsno + i];
if ( tmp >= 2 && tmp < 0xFFF7 )
{ /* The previous cluster is not in the same bad EB with the bad
* cluster, set its next pointer point to the new cluster. */
if (tmp < clsno || tmp >= clsno + num)
{
SWAP16((UINT16*)&rfat[tmp], (UINT16*)&m);
}
}
/* Record the EB's read buffer("rdbuf") has been modified */
mflag = 1;
/* Continue to handle the next bad cluster */
n++; qfat++;
break;
}
qfat++; n++; /* Check next new cluster */
}
/* If there are no free clusters, break out of the whole loop */
if (neweb < pdr->firstclblock)
break;
/* While a EB is passed, the EB should be update if modified. */
if (n == num)
{ /* The EB has been modified */
if (mflag == 1)
{
/* Call itself to write the data into the EB. If error happened in the writing
* process, it will be handled in the same way. And the function should
* never return error because the system must have collapsed until then
* and there are no good clusters to replace the bad ones. */
io_err_proc(driveno, neweb, rdbuf, en, NO);
FREE(rdbuf); rdbuf = NULL;
mflag = 0; /* Clear the modified flag */
i++; /* Next bad cluster */
}
/* Find next new EB */
pfat -= num; qfat = pfat;
n = 0; neweb-=en;
/* If the found EB is not modified, it means the current bad cluster(i)
* has been not replaced, so keep "i", do not increase it. */
continue;
}
i++; /* Next bad cluster */
}
/* If the bad cluster number is less than the free space in the EB, write it. */
if (mflag==1 && n<=num && neweb>=pdr->firstclblock)
{
io_err_proc(driveno, neweb, rdbuf, en, NO);
}
FREE(bad_fat_entries);
FREE(rep_fat_entries);
if (rdbuf) FREE(rdbuf);
return 1; /* OK */
}
INT dev_io_proc(UINT16 driveno, UINT32 sector, VOID *buffer, UINT16 count, INT reading)
{
_PC_BDEVSW *pdev;
DDRIVE *pdr;
UINT16 ltemp, ebnum, ebsize, ionum,offsetsec, *peb, *pfat, *pdirty;
UINT8 *devbuf, *pbuffer = buffer;
pdr = (DDRIVE *)NUF_Drive_Pointers[driveno];
/*
* MASTER BUFFER READ/WRITE
*/
ltemp = pdr->firstclblock;
if ( sector < ltemp )
{
//printf("op sector=%x count=%d FAT TABLE %s\n", sector, count, (reading==YES)?"R":"Write");
devbuf = pdr->fat_swap_structure.master_buffer + (sector<<9);
if (reading == YES)
memcpy(buffer, devbuf, count<<9);
else if (reading == NO)
memcpy1(devbuf, buffer, count<<9);
else if (reading == FLUSH)
{
/* FLUSH the data in the data buffer into device, and
* there is no error check here because the device
* must have been destroyed completely. */
ebsize = NUF_Drive_Erase_Size[driveno];
ebnum = 0;
for (ebnum = 0; ebnum < ltemp; ebnum += ebsize)
{
io_err_proc(driveno, ebnum, devbuf, ebsize, NO);
devbuf += ebsize<<9;
}
}
return 1;/*ok*/
}
/*
* DATA READ/WRITE
*/
devbuf = pdr->fat_swap_structure.data_buffer;
pdirty = &pdr->fat_swap_structure.data_buf_dirty;
peb = &pdr->fat_swap_structure.data_buf_eb;
ltemp = *peb;
ebsize = NUF_Drive_Erase_Size[driveno];
/*
* if device is NOR FLASH(that is driveno == 1), and
* only if operation is reading data,
* read the nor flash device directly for speed up.
*/
if(driveno == 1 && reading == YES)
{
pdev = &pc_bdevsw[driveno];
while(count)
{
ebnum = sector/ebsize;
offsetsec = sector%ebsize;
if ( ebnum != ltemp || ltemp == 0 ) /* read the device directly*/
{
ionum = ebsize-offsetsec;
if(count<=ionum)
{
if (pdev->io_proc(driveno, sector, pbuffer, count, YES))
return YES; /* read ok */
return NO; /* read failed */
}
else
{
if (!pdev->io_proc(driveno, sector, pbuffer, ionum, YES))
return NO; /* read failed */
}
sector += ionum;
count -= ionum;
pbuffer += ionum<<9;
}
else
{
if (offsetsec)
{
devbuf += (offsetsec<<9);
ionum = ebsize - offsetsec;
if (count<ionum)
ionum = count;
}
else
{
if (count<=ebsize)
ionum = count;
else
ionum = ebsize;
}
count -= ionum;
sector += ionum;
memcpy(pbuffer, devbuf, ionum<<9); /* read data from data buffer */
pbuffer += ionum<<9;
}
}
return YES; /* read ok */
}
/* The DATA BUFFER is out of date, the current data in the buffer
* should be saved into the real device. And the new data sent by
* the caller will be put into the buffer afterward or read from the
* buffer. */
while(count)
{
ebnum = sector/ebsize;
offsetsec = sector%ebsize;
devbuf = pdr->fat_swap_structure.data_buffer;
if ( ebnum != ltemp || ltemp == 0 )
{
if (ltemp != 0)
{
/* Save the current data in the buffer to the device */
if ( *pdirty == 1 )
{
*pdirty = 0;
if (!io_err_proc(driveno, ltemp*ebsize, devbuf, ebsize, NO))
return 0;/*error*/
}
if (reading == FLUSH)
return 1;/*ok*/
}
/* Record the new EB number */
*peb = ebnum;
ltemp = ebnum;
/* Load the new data from the device */
if (!io_err_proc(driveno, ebnum*ebsize, devbuf, ebsize, YES))
{
*peb = 0;
return 0;/*error*/
}
}
/* Check the EB according to the current data buffer is not BAD */
pdr = (DDRIVE *)NUF_Drive_Pointers[driveno];
pfat = (UINT16*)&pdr->fat_swap_structure.data_array[0];
pfat += (ebnum*ebsize-pdr->firstclblock)/pdr->secpalloc + 2;
if (*(pfat + 3 ) == 0xFFF7 )
{
*peb = 0; *pdirty = 0;
return 0;/*error*/
}
/* The DATA BUFFER is update, continue the operation. */
if (offsetsec)
{
devbuf += (offsetsec<<9);
ionum = ebsize - offsetsec;
if (count<ionum)
ionum = count;
}
else
{
if (count<=ebsize)
ionum = count;
else
ionum = ebsize;
}
count -= ionum;
sector += ionum;
if (reading == YES)
{
memcpy(pbuffer, devbuf, ionum<<9);
pbuffer += ionum<<9;
}
else
{
memcpy(devbuf, pbuffer, ionum<<9);
pbuffer += ionum<<9;
*pdirty = 1;
}
}
return 1;/*ok*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -