📄 device.c
字号:
/************************************************************************
*
* Copyright (c) 2004 by PESSIA
*
* PROPRIETARY RIGHTS of PESSIA are involved in the subject matter
* of this material. All manufacturing, reproduction, use, and sales
* rights pertaining to this subject matter are governed by the license
* agreement. The recipient of this software implicitly accepts the
* terms of the license.
*
*
*************************************************************************
*************************************************************************
* FILE NAME VERSION
*
* DEVICE.C
*
* COMPONENT
*
* Nucleus File
*
* DESCRIPTION
*
* This file contains Nuclues File32 application interface.
*
* DATA STRUCTURES
*
* None.
*
* FUNCTIONS
*
* XXXXXXXXXXX
*
* DEPENDENCIES
*
* pcdisk.h File common definitions
*
*************************************************************************/
#include "file\pcdisk.h"
#include "lmalloc.h"
extern _PC_BDEVSW pc_bdevsw[];
extern UNSIGNED *NUF_Drive_Pointers[];
extern INT NUF_Fat_Type[];
extern INT NUF_Drive_Fat_Size[];
#define MALLOC SysLmalloc
#define FREE SysLfree
static INT io_err_proc(INT16 driveno, UINT32 sector, VOID *buffer, UINT16 count, INT reading);
int memcpy1(void *dst, void *src, int num)
{
register unsigned int *pdst;
register unsigned int *psrc;
register int number;
int i;
//for(i=0;i<10000;i++);
pdst = (unsigned int *)dst;
psrc = (unsigned int *)src;
if(pdst == (unsigned int *)0x30cae4f8)
{
while(0);
}
for(i=0;i<1;i++);
for(number=0;number<num/4;number++)
{
*(pdst) = *(psrc);
pdst++;psrc++;
}
return number;
}
INT free_EB_proc(UINT16 *bad_fat_entries, INT16 driveno, UINT32 sector, VOID *buffer, UINT16 count, INT reading)
{
_PC_BDEVSW *pdev;
DDRIVE *pdr;
UINT16 *pfat, *qfat, *rfat, *vfat, neweb, next, clsno, tmp;
INT i, n, num, en;
UINT16 *rep_fat_entries;
/*
* Find a free EB to replace the bad one
*/
pdev = &pc_bdevsw[driveno];
pdr = (DDRIVE *)NUF_Drive_Pointers[driveno];
pfat = (UINT16*)&pdr->fat_swap_structure.data_array[0];
en = n = NUF_Drive_Erase_Size[driveno];
num = en/pdr->secpalloc; /* num is the number of a EB's FAT entries */
rep_fat_entries = (UINT16 *)MALLOC(num<<1);
if (rep_fat_entries == NULL)
return 0;/*error*/
neweb = pdr->numsecs - en;
clsno = (neweb - pdr->firstclblock)/pdr->secpalloc + 2;
pfat += clsno;
do
{
qfat = pfat;
for (i=0; i<num; i++)
{
if ( *qfat++ != 0 )
break;
}
/* Find a free EB */
if (i == num)
{
/*
* Replace the bad EB by the new one if have
*/
/* qfat is the new EB */
qfat = pfat;
/* pfat is the start of INVERSE FAT, clsno is the first cluster number of the bad EB */
vfat = (UINT16*)&pdr->fat_swap_structure.inv_data_array[0];
clsno = (sector - pdr->firstclblock)/pdr->secpalloc + 2;
pfat = vfat + clsno;
/* rfat is the start of FAT */
rfat = (UINT16*)&pdr->fat_swap_structure.data_array[0];
/* n is the start cluster's number of the new EB */
n = (neweb - pdr->firstclblock)/pdr->secpalloc + 2;
/* Modify each FAT entry in the free EB */
for (i=0; i<num; i++)
{
next = bad_fat_entries[i];
/* The new cluster's number is saved in the bad_fat_entries[] */
rep_fat_entries[i] = n;
/* 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*)&n);
}
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*)&n);
}
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*)&n);
}
/* If the bad cluster has a valid previous brother, modify it. */
if ( *pfat >= 2 && *pfat < 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 (*pfat < clsno || *pfat >= clsno + num)
{
SWAP16((UINT16*)&rfat[*pfat], (UINT16*)&n);
}
}
qfat++; pfat++; n++;
}
/* Write data into the new EB. */
n -= num; /* n is the start cluster's number of the new EB */
if (pdev->io_proc(driveno, neweb, buffer, count, reading))
{
FREE(bad_fat_entries);
FREE(rep_fat_entries);
return 1; /* OK */
}
/* The possibility of meeting error during the operation
* to the new EB is supposed to be very little!!! */
/* If error, Record the new EB as a BAD EB. */
next = 0xFFF7;
qfat = rfat + n;
for (i=0; i<num; i++)
SWAP16((UINT16 *)(qfat++), (UINT16*)&next);/*record bad flag*/
/* Get ready to find next free EB */
pfat = (UINT16*)&pdr->fat_swap_structure.data_array[0];
pfat += n;
}
/* Continue to find next free EB. */
pfat -= num;
neweb -= en;
}while (neweb>=pdr->firstclblock);
FREE(rep_fat_entries);
return 0;/*error*/
}
INT io_err_proc(INT16 driveno, UINT32 sector, VOID *buffer, UINT16 count, INT reading)
{
_PC_BDEVSW *pdev;
DDRIVE *pdr;
UINT16 *pfat, *qfat, *rfat, *vfat, neweb, next, clsno, tmp;
INT i, n, m, num, mflag, en;
UINT8 *rdbuf = NULL;
UINT16 *bad_fat_entries;
UINT16 *rep_fat_entries;
/*
* Check the destination is not BAD
*/
pdr = (DDRIVE *)NUF_Drive_Pointers[driveno];
clsno = (sector - pdr->firstclblock)/pdr->secpalloc + 2;
pfat = (UINT16*)&pdr->fat_swap_structure.data_array[0];
qfat = pfat + clsno;
if (*(qfat + 3 ) == 0xFFF7 )
return 0;/*error*/
/*
* Call the device interface to complete the IO operation.
*/
pdev = &pc_bdevsw[driveno];
if (pdev->io_proc(driveno, sector, buffer, count, reading))
return 1; /* OK */
/*
* Only when the FATs and BOOT and ROOT will be flushed into
* the device, it happens.
* And here return OK directly, because if error, the system will
* collapse during the next boot.
*/
if (sector < pdr->firstclblock)
return 1; /* OK */
/*
**********************************************************
* ERROR HANDLE PROCESS
**********************************************************
*/
/*
* Backup the FAT entries of the bad EB
*/
en = n = NUF_Drive_Erase_Size[driveno];
num = n/pdr->secpalloc; /* num is the number of a EB's FAT entries */
next = 0xFFF7; /*bad flag*/
if (reading == YES)
{
for (i=0; i<num; i++)
{
if (next == 0xFFFD)
{ /* Jump over the media flag "FFFD, FFFF" of FAT16 */
i++; qfat++; qfat++;
}
else
SWAP16((UINT16 *)(qfat++), &next);/*record bad flag*/
}
return 0;/*error*/
}
bad_fat_entries = (UINT16 *)MALLOC(num<<1);
if (bad_fat_entries == NULL)
return 0;/*error*/
for (i=0; i<num; i++)
{
if (*qfat == 0xFFFD)
{ /* Jump over the media flag "FFFD, FFFF" of FAT16 */
i++; qfat++; qfat++;
}
else
{
SWAP16(&bad_fat_entries[i], (UINT16 *)(qfat)); /*backup*/
SWAP16((UINT16 *)(qfat++), &next);/*record bad flag*/
}
}
/*
* Find a free EB to replace the bad one
*/
if (free_EB_proc(bad_fat_entries, driveno, sector, buffer, count, reading) != 0)
return 1; /* OK */
/*
* If no free EB, then find enough clusters to replace the bad EB.
*/
rep_fat_entries = (UINT16 *)MALLOC(num<<1);
if (rep_fat_entries == NULL)
{
FREE(bad_fat_entries);
return 0;/*error*/
}
/* neweb is the first sector number of the current EB to be checked */;
neweb = pdr->numsecs - en;
rfat = pfat = (UINT16*)&pdr->fat_swap_structure.data_array[0];
/* qfat is the new cluster to be checked, pfat is the new EB to be checked. */
clsno = (neweb - pdr->firstclblock)/pdr->secpalloc + 2;
pfat += clsno;
qfat = pfat;
/* rfat is the inverse FAT's start address */
vfat = (UINT16*)&pdr->fat_swap_structure.inv_data_array[0];
/* Check each cluster in the BAD EB, and move the used ones into a new place. */
i = 0; mflag = 0; n= 0;
clsno = (sector - pdr->firstclblock)/pdr->secpalloc + 2;
while (i < num)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -