📄 apiutil.c
字号:
/************************************************************************
*
* Copyright (c) 2001 by Accelerated Technology, Inc.
*
* PROPRIETARY RIGHTS of Accelerated Technology 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
*
* APIUTIL.C FILE 2.3
*
* COMPONENT
*
* Nucleus File
*
* DESCRIPTION
*
* Contains support code for user api level source code.
*
* DATA STRUCTURES
*
* None.
*
* FUNCTIONS
*
* pc_dskinit Mount a disk.
* pc_idskclose Unmount a disk.
* pc_fd2file Map a file descriptor to a
* 丂file structure.
* pc_allocfile Allocate a file structure.
* pc_freefile Release a file structure.
* pc_free_all_fil Release all file structures
* for a drive.
* pc_log_base_2 Calculate log2(N).
* pc_get_cwd Determine cwd string from
* current directory inode.
* pc_upstat Copy directory entry info
* to a user's stat buffer.
* DEPENDENCIES
*
* pcdisk.h File common definitions
*
*************************************************************************/
#include "file\pcdisk.h"
extern PC_FILE *mem_file_pool;
extern _PC_BDEVSW pc_bdevsw[];
extern UNSIGNED *NUF_Drive_Pointers[];
extern INT NUF_Fat_Type[];
extern INT NUF_Drive_Fat_Size[];
/************************************************************************
* FUNCTION
*
* pc_dskinit
*
* DESCRIPTION
*
* Given a valid drive number, read block zero and convert its
* contents to File syste drive information.
*
* AUTHOR
*
* Takahiro Takahashi
*
* INPUTS
*
* driveno Drive number
*
* OUTPUTS
*
* NU_SUCCESS Mount successful.
* NUF_FATCORE Fat cache table too small.
* NUF_NO_PARTITION No partition in disk.
* NUF_FORMAT Not formatted this disk.
* NUF_NO_MEMORY Can't allocate internal
* buffer.
* NUF_IO_ERROR Driver returned error.
* NUF_INTERNAL Nucleus FILE internal error.
*
*************************************************************************/
STATUS pc_dskinit(INT16 driveno)
{
STATUS ret_stat;
UINT8 b[512];
DDRIVE *pdr;
UINT16 min_needed;
FATSWAP *pfr;
UINT16 nblocks;
UINT8 FAR *pdata;
UINT32 fatoffset;
INT i;
UINT16 wvalue;
UINT32 ltemp;
/* get 1 block starting at 0 from driveno */
/* READ */
PC_DRIVE_IO_ENTER(driveno)
if ( !pc_bdevsw[driveno].io_proc(driveno, 0L, &b[0], (UINT16) 1, YES) )
{
PC_DRIVE_IO_EXIT(driveno)
pc_report_error(PCERR_INITREAD);
return(NUF_IO_ERROR);
}
PC_DRIVE_IO_EXIT(driveno)
pdr = (DDRIVE *)NUF_Drive_Pointers[driveno];
if (!pdr)
{
/* Allocate Drive memory */
pdr = (DDRIVE *)NUF_Alloc(sizeof(DDRIVE));
if (!pdr)
{
pc_report_error(PCERR_DRVALLOC);
return(NUF_NO_MEMORY);
}
/* Zero the structure so all of our initial values are right */
pc_memfill(pdr, sizeof(DDRIVE), (UINT8) 0);
pfr = &pdr->fat_swap_structure;
if (NUF_Drive_Fat_Size[driveno] < 256)
{
pfr->data_map_size = 256;
}
else
{
pfr->data_map_size = NUF_Drive_Fat_Size[driveno];
}
pfr->data_map = (UINT16 *)NUF_Alloc(sizeof(UINT16) * pfr->data_map_size);
if (!pfr->data_map)
{
pc_report_error(PCERR_DRVALLOC);
return(NUF_NO_MEMORY);
}
pfr->pdirty = (UINT8 *)NUF_Alloc(pfr->data_map_size >> 3 );
if (!pfr->pdirty)
{
pc_report_error(PCERR_DRVALLOC);
return(NUF_NO_MEMORY);
}
for (i = 0; i < pfr->data_map_size; i++)
{
pfr->data_map[i] = 0;
pfr->pdirty[i >> 3] = 0;
}
pfr->block_0_is_valid = 0;
pfr->base_block = 0;
pdr->opencount = 1;
NUF_Drive_Pointers[driveno] = (UNSIGNED *)pdr;
}
/* Verify that we have a good dos formatted disk */
if ( (b[0] != (UINT8) 0xE9) && (b[0] !=(UINT8) 0xEB) )
{
pc_report_error(PCERR_INITMEDI);
pdr->opencount = 0;
return(NUF_FORMAT);
}
/* This drive is FAT file system */
pdr->fs_type = FAT_FILE_SYSTEM;
/* Now load the structure from the buffer */
copybuff(&pdr->oemname[0],&b[3],8);
SWAP16((UINT16 *)&pdr->bytspsector, (UINT16 *)&b[0xb]);
pdr->secpalloc = b[0xd];
SWAP16((UINT16 *)&pdr->fatblock,(UINT16 *)&b[0xe]);
pdr->numfats = b[0x10];
SWAP16((UINT16 *)&pdr->numroot,(UINT16 *)&b[0x11]);
SWAP16(&wvalue,(UINT16 *)&b[0x13]);
pdr->numsecs = wvalue;
pdr->mediadesc = b[0x15];
SWAP16(&wvalue,(UINT16 *)&b[0x16]);
pdr->secpfat = wvalue;
SWAP16((UINT16 *)&pdr->secptrk,(UINT16 *)&b[0x18]);
SWAP16((UINT16 *)&pdr->numhead,(UINT16 *)&b[0x1a]);
SWAP32((UINT32 *)&pdr->numhide,(UINT32 *)&b[0x1c]);
SWAP32((UINT32 *)&pdr->bignumsecs,(UINT32 *)&b[0x20]);
/* # secs if > 32M (4.0) */
/******************************************************************
Driver set drive fat type information from MBR
PART_UNKNOWN(00h) Unknown.
PART_DOS2_FAT(01h) 12-bit FAT.
PART_DOS3_FAT(04h) 16-bit FAT. Partition smaller than 32MB.
PART_EXTENDED(05h) Extended MS-DOS Partition.
PART_DOS4_FAT(06h) 16-bit FAT. Partition larger than or equal to 32MB.
PART_DOS32(0Bh) 32-bit FAT. Partition up to 2047GB.
PART_DOS32X(0Ch) Same as PART_DOS32(0Bh), but uses Logical Block Address
Int 13h extensions.
PART_DOSX13(0Eh) Same as PART_DOS4_FAT(06h), but uses Logical Block Address
Int 13h extensions.
PART_DOSX13X(0Fh) Same as PART_EXTENDED(05h), but uses Logical Block Address
Int 13h extensions.
******************************************************************/
switch (NUF_Fat_Type[driveno])
{
case 1:
pdr-> fasize = 3;
break;
case 4:
case 6:
case 0x0e:
pdr-> fasize = 4;
break;
case 0x0b:
case 0x0c:
pdr-> fasize = 8;
break;
default:
if ( (b[0x36] == 'F') && (b[0x37] == 'A') && (b[0x38] == 'T') && (b[0x39] == '1') )
{
if (b[0x3a] == '2')
pdr-> fasize = 3;
if (b[0x3a] == '6')
pdr-> fasize = 4;
}
else if ( (b[0x52] == 'F') && (b[0x53] == 'A') && (b[0x54] == 'T') )
{
if ( (b[0x55] == '1') && (b[0x56] == '6') )
pdr-> fasize = 4;
if ( (b[0x55] == '3') && (b[0x56] == '2') )
pdr-> fasize = 8;
}
}
/* Check if running on a DOS (4.0) huge partition */
/* If traditional total # sectors is zero, use value in extended BPB */
if (pdr->numsecs == 0L)
pdr->numsecs = pdr->bignumsecs;
/* Not set the NUF_Fat_Type */
if (pdr->fasize == 0)
{
/* On trial calculate the clusters */
pdr->maxfindex = (UINT32)
(1 + (pdr->numsecs)/pdr->secpalloc);
if (pdr->maxfindex < 0x0fff)
pdr->fasize = 3;
else if (pdr->maxfindex < 0xffff)
pdr->fasize = 4;
else
{
pdr->opencount = 0;
return(NUF_FORMAT);
}
}
if (pdr->fasize <= 4)
{ /* FAT12/FAT16 */
pdr->phys_num = b[0x24];
pdr->xtbootsig = b[0x26];
SWAP16((UINT16 *)&pdr->volid,(UINT16 *)&b[0x27]); /* Unique number per volume (4.0) */
copybuff(&pdr->vollabel[0],&b[0x2b],11); /* Volume label (4.0) */
/* The first block of the root is just past the fat copies */
pdr->rootblock = pdr->fatblock + pdr->secpfat * pdr->numfats;
/* The first block of the cluster area is just past the root */
/* Round up if we have to */
pdr->firstclblock = pdr->rootblock +
(pdr->numroot + INOPBLOCK - 1)/INOPBLOCK;
if (pdr->fasize == 3)
min_needed =(UINT16)(pdr->secpfat & 0x00FFFFL);
else
min_needed = 12;
/* set the pointer to where to look for free clusters to the contiguous
area. On the first call to write this will hunt for the real free
blocks. */
pdr->free_contig_pointer = 2L;
/* Keep track of how much free space is on the drive. (This will
speed up pc_free()) when calculating free space */
pdr->free_clusters_count = 0L;
}
else
{ /* FAT32 */
SWAP32((UINT32 *)&pdr->bigsecpfat,(UINT32 *)&b[0x24]);
SWAP16((UINT16 *)&pdr->fat_flag,(UINT16 *)&b[0x28]);
SWAP16((UINT16 *)&pdr->file_version,(UINT16 *)&b[0x2a]);
SWAP32((UINT32 *)&pdr->rootdirstartcl,(UINT32 *)&b[0x2c]); /* Root dir start cluster */
SWAP32((UINT32 *)&pdr->volid,(UINT32 *)&b[0x43]); /* Unique number per volume (4.0) */
copybuff(&pdr->vollabel[0],&b[0x47],11); /* Volume label (4.0) */
/* The first block of the root is given */
pdr->rootblock = pdr->fatblock + pdr->bigsecpfat * pdr->numfats;
if (pdr->rootdirstartcl != 2L)
{
if (pdr->rootdirstartcl > 2L)
pdr->rootblock += ((pdr->rootdirstartcl - 2L) * pdr->secpalloc);
else
{
pdr->opencount = 0;
return(NUF_FORMAT);
}
}
/* The first block of the cluster area is the root dir */
pdr->firstclblock = pdr->rootblock;
min_needed = 16;
pdr->secpfat = pdr->bigsecpfat;
SWAP16((UINT16 *)&pdr->fsinfo,(UINT16 *)&b[0x30]);
/* Read the File System INFOmation */
PC_DRIVE_IO_ENTER(driveno)
if ( !pc_bdevsw[driveno].io_proc(driveno, (UINT32) pdr->fsinfo, &b[0], (UINT16) 1, YES) )
{
PC_DRIVE_IO_EXIT(driveno)
pc_report_error(PCERR_INITREAD);
pdr->opencount = 0;
return(NUF_IO_ERROR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -