📄 lowl.c
字号:
BOOL pc_pfpbyte( DDRIVE *pdr, COUNT index, UCOUNT *pvalue);
Get a byte from the FAT at index and put the value at *value. Return YES if
everything worked.
Note: FAT page swaps will occur if they are needed. Called by pc_faxx().
BOOL pc_pfgbyte( DDRIVE *pdr, COUNT index, UCOUNT *value);
Flush any dirty blocks from the current FAT page. Called by pc_flushfat()
BOOL 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 */
UTINY FAR *pc_pfswap(DDRIVE *pdr, UCOUNT index, BOOL for_write) /*__fn__*/
{
FATSWAP *pfs = &pdr->fat_swap_structure;
BLOCKT newblock;
UCOUNT block_offset_in_fat;
UCOUNT i;
UTINY FAR *pdata;
UTINY uc;
UCOUNT byte_offset;
UCOUNT bit_offset;
UCOUNT data_block_to_use;
ULONG ltemp;
/* Convert the index (in words) to block values
divide by 256 since there are 256 FAT entries per block */
block_offset_in_fat = (UCOUNT) (index >> 8);
if (block_offset_in_fat >= pdr->secpfat) /* Check range */
return (NULL);
/* 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 ( ((block_offset_in_fat == 0) && pfs->block_0_is_valid) ||
(pfs->data_map[block_offset_in_fat] != 0) )
{
/* Already in our cache. set up a pointer to it */
data_block_to_use = pfs->data_map[block_offset_in_fat];
ltemp = (ULONG) data_block_to_use;
pdata = pfs->data_array + (ltemp << 9);
}
else
{
/* Not mapped, we have to read it in */
if (pfs->n_blocks_used != pfs->n_blocks_total)
{
/* If we haven't reached steady state: use core until we
get there. */
data_block_to_use = pfs->n_blocks_used;
pfs->n_blocks_used += 1;
}
else
{
/* Flush the buffer
Later make this more selective by only flushing the block we
are swapping */
if (!pc_pfflush(pdr))
return(NULL);
/* Select the block to swap out. Use a simple round-robin
selection algorithm: pfs->n_to_swap is the current
target for swapping (block 0 is never swapped out) */
if (!pfs->n_to_swap)
pfs->n_to_swap += 1;
if (pfs->n_to_swap >= pdr->secpfat)
pfs->n_to_swap = 1;
data_block_to_use = 0;
while (data_block_to_use == 0)
{
for (i = pfs->n_to_swap; i < pdr->secpfat; i++)
{
if (pfs->data_map[i])
{
/* swap this one out */
data_block_to_use = pfs->data_map[i];
pfs->data_map[i] = 0;
pfs->n_to_swap =(UCOUNT)(i+1);
break;
}
}
if (!data_block_to_use)
pfs->n_to_swap = 1; /* Start at the beginining */
}
} /* END IF we had to swap */
/* Whether we are reusing a block or still coming up to speed.
if the block is not currently in our pool we must mark the
data block used and read it in */
pfs->data_map[block_offset_in_fat] = (UTINY) data_block_to_use;
newblock = pdr->fatblock + block_offset_in_fat;
ltemp = (ULONG) data_block_to_use;
pdata = pfs->data_array + (ltemp << 9);
/* READ */
PC_DRIVE_IO_ENTER(pdr->driveno)
if (!pc_bdevsw[pdr->driveno].io_proc(pdr->driveno,newblock,pdata,1,YES))
{
pfs->data_map[block_offset_in_fat] = 0;
PC_DRIVE_IO_EXIT(pdr->driveno)
return(NULL);
}
pfs->block_0_is_valid = 1;
PC_DRIVE_IO_EXIT(pdr->driveno)
} /* END IF the data needed reading in */
/* If we should mark it dirty do so in the bit map */
if (for_write)
{
byte_offset = (UCOUNT) (block_offset_in_fat >> 3); /* divide by 8 */
bit_offset = (UCOUNT) (block_offset_in_fat & 0x7); /* mod 8 */
uc = 1;
uc <<= bit_offset;
pfs->pdirty[byte_offset] |= uc;
}
return(pdata);
}
/* Put a WORD value into the fat at index */
BOOL pc_pfpword(DDRIVE *pdr, UCOUNT index, UCOUNT *pvalue) /*__fn__*/
{
UCOUNT FAR *ppage;
UCOUNT offset;
/* Make sure we have access to the page. Mark it for writing */
ppage = (UCOUNT FAR *)pc_pfswap(pdr,index,YES);
if (!ppage)
return(NO);
else
{
/* there are 256 entries per page */
offset = (UCOUNT) (index & 0xff);
ppage[offset] = *pvalue;
}
return(YES);
}
/* Get a WORD value from the fat at index */
BOOL pc_pfgword(DDRIVE *pdr, UCOUNT index, UCOUNT *value) /*__fn__*/
{
UCOUNT FAR *ppage;
UCOUNT offset;
/* Make sure we have access to the page. Don't Mark it for writing */
ppage = (UCOUNT FAR *)pc_pfswap(pdr,index,NO);
if (!ppage)
return(NO);
else
{
/* there are 256 entries per page */
offset = (UCOUNT) (index & 0xff);
*value = ppage[offset];
}
return(YES);
}
/* Consult the dirty fat block list and write any. write all copies
of the fat */
BOOL pc_pfflush(DDRIVE *pdr) /*__fn__*/
{
FATSWAP *pfs = &pdr->fat_swap_structure;
UTINY FAR *pdata;
COUNT i;
UCOUNT j;
UTINY uc;
UTINY bit_in_array;
UCOUNT offset_div_8;
BLOCKT blockno;
UCOUNT offset_in_block_map;
ULONG data_offset;
ULONG baseblock; /* BUG FIX */
PC_DRIVE_IO_ENTER(pdr->driveno)
for (j = 0; j < pdr->numfats;j++)
{
baseblock = (ULONG) j; /* BUG FIX */
baseblock *= pdr->secpfat; /* BUG FIX */
baseblock += pdr->fatblock; /* BUG FIX */
for (offset_div_8 = 0,i = 0; i < 32; i++,offset_div_8 += 8)
{
uc = pfs->pdirty[i];
bit_in_array = 0;
while (uc)
{
if (uc & 0x01) /* If bit is dirty. */
{
/* add (by oring) the byte index and the bit index
to get the block offset in the fat */
offset_in_block_map = (UCOUNT)(offset_div_8 | bit_in_array);
/* map the offset to data through our map */
data_offset = (ULONG) pfs->data_map[offset_in_block_map];
/* Convert block offset to byte offset */
data_offset <<= 9;
/* Get its address in our data array */
pdata = pfs->data_array + data_offset;
/* Convert offset in fat to logical disk block */
blockno = baseblock + offset_in_block_map; /* BUG FIX */
/* WRITE IT */
if(!pc_bdevsw[pdr->driveno].io_proc(pdr->driveno,blockno,pdata,1,NO))
{
pc_report_error(PCERR_FAT_FLUSH);
PC_DRIVE_IO_EXIT(pdr->driveno)
return(NO);
}
}
uc >>= 1;
bit_in_array++;
}
}
}
/* Clear the dirty map */
pc_memfill(pfs->pdirty, 32, (UTINY) 0);
PC_DRIVE_IO_EXIT(pdr->driveno)
return (YES);
}
/****************************************************************************
PC_GBLK0 - Read block 0 and load values into a a structure
Description
Given a valid drive number, read block zero and convert
its contents from intel to native byte order.
Returns
Returns YES if all went well.
****************************************************************************/
/* read block zero */
BOOL pc_gblk0(UCOUNT driveno, struct pcblk0 *pbl0) /*__fn__*/
{
UTINY b[512];
/* get 1 block starting at 0 from driveno */
/* READ */
PC_DRIVE_IO_ENTER(driveno)
if (!pc_bdevsw[driveno].io_proc(driveno, 0L ,&b[0],1,YES))
{
PC_DRIVE_IO_EXIT(driveno)
return(NO);
}
PC_DRIVE_IO_EXIT(driveno)
/* Now load the structure from the buffer */
pbl0->jump = b[0];
copybuff( &pbl0->oemname[0],&b[3],8);
pbl0->oemname[8] = '\0';
pbl0->bytspsector = to_WORD(&b[0xb]);
pbl0->secpalloc = b[0xd];
pbl0->secreserved = to_WORD(&b[0xe]);
pbl0->numfats = b[0x10];
pbl0->numroot = to_WORD(&b[0x11]);
pbl0->numsecs = to_WORD(&b[0x13]);
pbl0->mediadesc = b[0x15];
pbl0->secpfat = to_WORD(&b[0x16]);
pbl0->secptrk = to_WORD(&b[0x18]);
pbl0->numhead = to_WORD(&b[0x1a]);
pbl0->numhide = to_WORD(&b[0x1c]);
pbl0->numhide2 = to_WORD(&b[0x1e]);
pbl0->numsecs2 = to_DWORD(&b[0x20]); /* # secs if > 32M (4.0) */
pbl0->physdrv = b[0x24]; /* Physical Drive No. (4.0) */
pbl0->filler = b[0x25]; /* Reserved (4.0) */
pbl0->xtbootsig = b[0x26]; /* Extended signt 29H if 4.0 stuf valid */
pbl0->volid = to_DWORD(&b[0x27]); /* Unique number per volume (4.0) */
copybuff( &pbl0->vollabel[0],&b[0x2b],11); /* Volume label (4.0) */
/*
* printf ("Jump %d\n",pbl0->jump);
* printf ("Oem NAME %s\n",pbl0->oemname);
* printf ("Bytspsec %d\n",pbl0->bytspsector);
* printf ("secpallc %d\n",pbl0->secpalloc);
* printf ("secres %d\n",pbl0->secreserved);
* printf ("numfat %d\n",pbl0->numfats);
* printf ("numrot %d\n",pbl0->numroot);
* printf ("numsec %d\n",pbl0->numsecs);
* printf ("mediac %d\n",pbl0->mediadesc);
* printf ("secfat %d\n",pbl0->secpfat);
* printf ("sectrk %d\n",pbl0->secptrk);
* printf ("numhed %d\n",pbl0->numhead);
* printf ("numhide %d\n",pbl0->numhide);
*/
return(YES);
}
/***************************************************************************
PC_CLZERO - Fill a disk cluster with zeroes
Description
Write zeroes into the cluster at clusterno on the drive pointed to by
pdrive. Used to zero out directory and data file clusters to eliminate
any residual data.
Returns
Returns NO on a write erro.
****************************************************************************/
/* Write zeros to all blocks in a cluster */
BOOL pc_clzero(DDRIVE *pdrive, UCOUNT cluster) /*__fn__*/
{
BLKBUFF *pbuff;
UCOUNT i;
BLOCKT currbl;
currbl = pc_cl2sector(pdrive , cluster);
if (!currbl)
return (NO);
/*Init and write a block for each block in cl. Note: init clears the core*/
for (i = 0; i < pdrive->secpalloc; i++, currbl++ )
{
pbuff = pc_init_blk( pdrive , currbl);
if (!pbuff)
{
return (NO);
}
if ( !pc_write_blk ( pbuff ) )
{
pc_free_buf(pbuff,YES);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -