📄 lowl.c
字号:
****************************************************************************/
/* Note: The caller locks the fat before calling this routine */
CLUSTERTYPE pc_get_chain(DDRIVE *pdr, CLUSTERTYPE start_cluster, CLUSTERTYPE *pnext_cluster, CLUSTERTYPE n_clusters) /*__fn__*/
{
CLUSTERTYPE clno;
CLUSTERTYPE n_contig;
CLUSTERTYPE value;
BOOLEAN nibs_3;
BOOLEAN nibs_4;
#if (FAT32)
BOOLEAN nibs_8;
#endif
dword _Oxffffff7ul;
if ( (start_cluster < 2) || (start_cluster > pdr->maxfindex))
return (0);
nibs_3 = nibs_4 = FALSE;
#if (FAT32)
nibs_8 = FALSE;
#endif
if (pdr->fasize == 3)
nibs_3 = TRUE;
else if (pdr->fasize == 4)
nibs_4 = TRUE;
#if (FAT32)
else if (pdr->fasize == 8)
nibs_8 = TRUE;
#endif
else
return(0);
clno = start_cluster;
n_contig = 1;
*pnext_cluster = 0;
/* Get each FAT entry. If its value points to the next contiguous entry
continue. Otherwise we have reached the end of the contiguous chain.
At which point we return the number of contig's found and by reference
the address of the FAT entry beginning the next chain segment.
*/
while(TRUE)
{
if (!pc_faxx(pdr, clno, &value))
return(0);
/* check for a bad cluster and skip it if we see it */
_Oxffffff7ul = 0xffffff7ul;
if ( ( value == 0xff7 && nibs_3)
|| (value == 0xfff7 && nibs_4)
#if (FAT32)
|| (value == _Oxffffff7ul && nibs_8)
#endif
)
{
clno = (CLUSTERTYPE)(clno + 1);
}
/* check for end markers set next cluster to the last
cluster in the chain if we are at the end */
else if ( ( value > 0xff7 && nibs_3)
|| (value > 0xfff7 && nibs_4)
#if (FAT32)
|| (value >= _Oxffffff7ul && nibs_8)
#endif
)
{
value = clno;
break;
}
else if (value == ++clno)
{
if (n_contig >= n_clusters)
break;
n_contig++;
}
else
break;
}
*pnext_cluster = value;
return (n_contig);
}
RTFS_FILE(pfaxxtrm.c, pc_pfaxxterm)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if RTFS_WRITE
/******************************************************************************
PC_PFAXXTERM - Write a terminating value to the FAT at clno.
Description
Given a DDRIVE,cluster number and value. Write the value 0xffffffff or
0xffff in the fat at clusterno. Handle 32, 16 and 12 bit fats correctly.
Returns
FALSE if an io error occurred during fat swapping, else TRUE
*****************************************************************************/
/* Given a clno & fatval Put the value in the table at the index (clno) */
/* Note: The caller locks the fat before calling this routine */
BOOLEAN pc_pfaxxterm(DDRIVE *pdr, CLUSTERTYPE clno) /*__fn__*/
{
#if (FAT32)
if (pdr->fasize == 8)
return(pc_pfaxx(pdr, clno, 0x0ffffffful));
else
#endif
return(pc_pfaxx(pdr, clno, 0xffff));
}
#endif
RTFS_FILE(pfaxx.c, pc_pfaxx)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if (RTFS_WRITE)
/******************************************************************************
PC_PFAXX - Write a value to the FAT at clno.
Description
Given a DDRIVE,cluster number and value. Write the value in the fat
at clusterno. Handle 16 and 12 bit fats correctly.
Returns
No if an io error occurred during fat swapping, else TRUE.
*****************************************************************************/
/* Given a clno & fatval Put the value in the table at the index (clno) */
/* Note: The caller locks the fat before calling this routine */
BOOLEAN pc_pfaxx(DDRIVE *pdr, CLUSTERTYPE clno, CLUSTERTYPE value) /*__fn__*/
{
union align1 {
byte wrdbuf[4]; /* Temp storage area */
word fill[2];
} u;
CLUSTERTYPE nibble,index,offset, t;
pdr->fat_is_dirty = TRUE;
if (pdr->fasize == 3) /* 3 nibble ? */
{
nibble = (CLUSTERTYPE)(clno * 3);
index = (CLUSTERTYPE)(nibble >> 2);
offset = (CLUSTERTYPE)(clno & 0x03);
/* Read the first word */
if (!pc_fword( pdr, index, (word *) &u.wrdbuf[0], FALSE ))
return(FALSE);
/*
| W0 | W1 | W2 |
A1 A0 B0 A2 B2 B1 C1 C0 D0 C2 D2 D1
xx xx xx
*/
if (offset == 0) /* (A2 << 8) | A1 A2 */
{
/* Low nibble of b[1] is hi nibble of value */
u.wrdbuf[1] &= 0xf0;
t = (CLUSTERTYPE)((value >> 8) & 0x0f);
u.wrdbuf[1] |= (byte) t;
/* b[0] is lo byte of value */
t = (CLUSTERTYPE)(value & 0x00ff);
u.wrdbuf[0] = (byte) t;
if (!pc_fword( pdr, index, (word *) &u.wrdbuf[0], TRUE ))
return (FALSE);
}
/*
| W0 | W1 | W2 |
A1 A0 B0 A2 B2 B1 C1 C0 D0 C2 D2 D1
xx xx xx
*/
else if (offset == 1) /* (B1 B2 << 4) | B0 */
{
/* Hi nibble of b[1] is lo nibble of value */
u.wrdbuf[1] &= 0x0f;
t = (CLUSTERTYPE)((value << 4) & 0x00f0);
u.wrdbuf[1] |= (byte)t;
if (!pc_fword( pdr, index, (word *) &u.wrdbuf[0], TRUE ))
return (FALSE);
/* b[0] is hi byte of value */
if (!pc_fword( pdr, (word)(index+1), (word *) &u.wrdbuf[0], FALSE ))
return(FALSE);
t = (CLUSTERTYPE)((value >> 4) & 0x00ff);
u.wrdbuf[0] = (byte) t;
if (!pc_fword( pdr, (word)(index+1), (word *) &u.wrdbuf[0], TRUE ))
return (FALSE);
}
/*
| W0 | W1 | W2 |
A1 A0 B0 A2 B2 B1 C1 C0 D0 C2 D2 D1
xx xx xx
*/
else if (offset == 2) /*(C2 << 8) | C1 C2 */
{
/* b[1] = low byte of value */
t = (CLUSTERTYPE)(value & 0x00ff);
u.wrdbuf[1] = (byte) t;
if (!pc_fword( pdr, index, (word *) &u.wrdbuf[0], TRUE ))
return (FALSE);
/* lo nibble of b[0] == hi nibble of value */
if (!pc_fword( pdr, (word)(index+1), (word *) &u.wrdbuf[0], FALSE ))
return(FALSE);
u.wrdbuf[0] &= 0xf0;
t = (CLUSTERTYPE)((value >> 8) & 0x0f);
u.wrdbuf[0] |= (byte) t;
if (!pc_fword( pdr, (word)(index+1), (word *) &u.wrdbuf[0], TRUE ))
return (FALSE);
}
/*
| W0 | W1 | W2 |
A1 A0 B0 A2 B2 B1 C1 C0 D0 C2 D2 D1
xx xx xx
*/
else if (offset == 3) /* (D2 D1) << 4 | D0 */
{
/* Hi nibble b[0] == low nible of value */
u.wrdbuf[0] &= 0x0f;
t = (CLUSTERTYPE)((value << 4) & 0x00f0);
u.wrdbuf[0] |= (byte) t;
t = (CLUSTERTYPE)((value >> 4) & 0x00ff);
u.wrdbuf[1] = (byte) t;
if (!pc_fword( pdr, index, (word *) &u.wrdbuf[0], TRUE ))
return (FALSE);
}
}
#if (FAT32) /* FAT32 only supported if FAT swapping is enabled */
else if (pdr->fasize == 8)
{
fr_DWORD(&u.wrdbuf[0],value); /*X*/
/* Now put the values back into the FAT */
if (!pc_pfpdword( pdr, clno, (dword *) &u.wrdbuf[0] ))
{
return (FALSE);
}
}
#endif /* FAT32 */
else /* 16 BIT entries */
{
fr_WORD((byte *) &u.wrdbuf[0],(word)value); /*X*/
/* Now put the values back into the FAT */
if (!pc_fword( pdr, clno, (word *) &u.wrdbuf[0], TRUE ))
{
return (FALSE);
}
}
return (TRUE);
}
#endif
RTFS_FILE(fatsw.c, pc_fatsw)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
/***************************************************************************
PC_FATSW - FAT Access code when fat buffering is enabled.
Summary
Free all core associated with the drive's fat
void pc_pfclose( DDRIVE *pdr);
Flush the current page (if needed. And read in a new page such that
"index" is contained therein. (Called by pc_pfpbyte() and pc_pfgbyte())
BOOLEAN pc_pfswap( DDRIVE *pdr, word index);
Put a byte (value) into the FAT at index. Return TRUE if everything worked.
Note: FAT page swaps will occur if they are needed. Called by pc_pfaxx().
BOOLEAN pc_pfpbyte( DDRIVE *pdr, int index, word *pvalue);
Get a byte from the FAT at index and put the value at *value. Return TRUE if
everything worked.
Note: FAT page swaps will occur if they are needed. Called by pc_faxx().
BOOLEAN pc_pfgbyte( DDRIVE *pdr, int index, word *value);
Flush any dirty blocks from the current FAT page. Called by pc_flushfat()
BOOLEAN pc_pfflush( DDRIVE *pdr);
Description
Provide a cacheing mechanism for the file allocation table. We have a
byte map table indicating the offset in our data cache for each block
in the FAT. If the value at dat_map[block] is zero the block is not
cached. We also maintain a bitmap of each block in the FAT. If the
bit is set the corresponding block must be flushed.
Returns
Example
****************************************************************************/
/* Flush buffers and then swap in the page containing index */
/* Note: This routine must be called first with index == 0. see pc_dskinit */
/* Note: The caller locks the fat before calling this routine */
PFBYTE pc_pfswap(DDRIVE *pdr, CLUSTERTYPE index, BOOLEAN for_write) /*__fn__*/
{
FATSWAP *pfs = &pdr->fat_swap_structure;
BLOCKT newblock;
CLUSTERTYPE block_offset_in_fat;
CLUSTERTYPE i;
PFBYTE pdata;
byte uc;
CLUSTERTYPE byte_offset; /*FAT32*/
CLUSTERTYPE bit_offset; /*FAT32*/
CLUSTERTYPE data_block_to_use; /*FAT32*/
#if (FAT32)
dword *datamp;
dword block_tag;
word fat_cache_index;
#endif
dword ltemp;
/* Convert the index (in words) to block values
divide by 256 since there are 256 FAT entries per block */
#if (FAT32)
if (pdr->fasize == 8)
{
block_offset_in_fat = (dword)(index >> 7);
fat_cache_index = (word)(block_offset_in_fat % pfs->n_blocks_total);
block_tag = (dword)(block_offset_in_fat / pfs->n_blocks_total);
block_tag |= 0x80000000ul;
datamp = (dword*) pfs->data_map;
}
else
#endif
block_offset_in_fat = (word) (index >> 8);
if (block_offset_in_fat >= pdr->secpfat) /* Check range */
return (0);
/* check if the block is already mapped.
Notice we use block_0_is_valid as a flag denoting whether
the first block in the fat is buffered. We did this because
we want to use:
data_map[block_offset_in_fat] == 0;
Where data_map[] indicates the offset into our cache memory
(in blocks) of the the cached buffer.
To indicate that the disk block is not cached. Since offset 0
is a valid number we chose to preload the first disk block in the
fat to location 0 in our buffer cache. After this has occured we
set block_0_is_valid. Yuk, but effective..
*/
#if (FAT32)
if (pdr->fasize == 8)
{
ltemp = (dword) fat_cache_index;
#if (FAT_BUFFER_SIZE > 63) /* Ugly conditional until sure */
pdata = pfs->data_array + (ltemp << 9);
#else
pdata = pfs->data_array + (word)(ltemp << 9);
#endif
if (datamp[fat_cache_index] != block_tag)
{
#if RTFS_WRITE
if (!pc_pfflush(pdr))
return(0);
#endif
/* READ */
datamp[fat_cache_index] = block_tag;
newblock = pdr->fatblock + block_offset_in_fat;
if (!devio_read(pdr->driveno,newblock,pdata,1, FALSE))
{
datamp[fat_cache_index] = 0;
return(0);
}
}
block_offset_in_fat = fat_cache_index;
}
else
#endif /* FAT32 */
if ( ((block_offset_in_fat == 0) && pfs->block_0_is_valid) ||
(pfs->data_map[(int)block_offset_in_fat] != 0) )
{
/* Already in our cache. set up a pointer to it */
data_block_to_use = pfs->data_map[(int)block_offset_in_fat];
ltemp = (dword) data_block_to_use;
#if (FAT_BUFFER_SIZE > 63) /* Ugly conditional until sure */
pdata = pfs->data_array + (ltemp << 9);
#else
pdata = pfs->data_array + (word) (ltemp << 9);
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -