⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatfs_supp.c

📁 嵌入式FAT文件系统
💻 C
📖 第 1 页 / 共 5 页
字号:
//==========================================================================
//
//      fatfs_supp.c
//
//      FAT file system support functions
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):           Savin Zlobec <savin@elatec.si> 
// Date:                2003-06-30
//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <pkgconf/fs_fat.h>
#include <pkgconf/infra.h>

#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_ass.h>
#include <cyg/infra/cyg_trac.h>
#include <cyg/infra/diag.h>
#include <cyg/io/io.h>
#include <cyg/fs/fatfs.h>
#include <blib/blib.h>
#include <cyg/io/Disk.h>
#include <cyg/io/Diskio.h>
#include <sys/types.h>
#include <ctype.h>

#include "fatfs.h"

//==========================================================================
// FAT defines & macros

// -------------------------------------------------------------------------
// FAT dir entry attributes macros

#define DENTRY_IS_RDONLY(_dentry_)  (S_FATFS_ISRDONLY((_dentry_)->attr))
#define DENTRY_IS_HIDDEN(_dentry_)  (S_FATFS_ISHIDDEN((_dentry_)->attr))
#define DENTRY_IS_SYSTEM(_dentry_)  (S_FATFS_ISSYSTEM((_dentry_)->attr))
#define DENTRY_IS_VOLUME(_dentry_)  (S_FATFS_ISVOLUME((_dentry_)->attr))
#define DENTRY_IS_DIR(_dentry_)     (S_FATFS_ISDIR((_dentry_)->attr))
#define DENTRY_IS_ARCHIVE(_dentry_) (S_FATFS_ISARCHIVE((_dentry_)->attr))
#define DENTRY_IS_LONG_NAME(_dentry_) (S_FATFS_ISLONG_NAME((_dentry_)->attr))
#define DENTRY_IS_LONG_NAME_MASK(_dentry_) (S_FATFS_ISLONG_NAME_MASK((_dentry_)->attr))

#define DENTRY_IS_DELETED(_dentry_) \
    (0xE5 == (cyg_uint8)((_dentry_)->name[0]))

#define DENTRY_IS_ZERO(_dentry_) \
    (0x00 == (cyg_uint8)((_dentry_)->name[0]))

// -------------------------------------------------------------------------
// FAT disk data access macros

// FIXME: support big endian machines!
   
#define GET_BYTE(_data_, _var_, _off_) \
    (_var_ = *( ((cyg_uint8 *)_data_) + (_off_) ) )

#define GET_WORD(_data_, _var_, _off_)                      \
    (_var_ = *( ((cyg_uint8 *)_data_) + (_off_) ) |         \
             *( ((cyg_uint8 *)_data_) + (_off_) + 1 ) << 8)

#define GET_DWORD(_data_, _var_, _off_)                         \
    (_var_ = *( ((cyg_uint8 *)_data_) + (_off_))             |  \
             *( ((cyg_uint8 *)_data_) + (_off_) + 1 ) << 8   |  \
             *( ((cyg_uint8 *)_data_) + (_off_) + 2 ) << 16  |  \
             *( ((cyg_uint8 *)_data_) + (_off_) + 3 ) << 24)

#define GET_BYTES(_data_, _var_, _size_, _off_) \
    memcpy((void *)(_var_), (void*)(((cyg_uint8 *)_data_)+(_off_)),_size_)

#define SET_BYTE(_data_, _val_, _off_) \
    (*( ((cyg_uint8 *)_data_) + (_off_) ) = _val_)

#define SET_WORD(_data_, _val_, _off_)                                   \
    do {                                                                 \
        *( ((cyg_uint8 *)_data_) + (_off_) )     = _val_         & 0xFF; \
        *( ((cyg_uint8 *)_data_) + (_off_) + 1 ) = (_val_ >> 8)  & 0xFF; \
    } while (0)

#define SET_DWORD(_data_, _val_, _off_)                                  \
    do {                                                                 \
        *( ((cyg_uint8 *)_data_) + (_off_) )     = _val_         & 0xFF; \
        *( ((cyg_uint8 *)_data_) + (_off_) + 1 ) = (_val_ >> 8)  & 0xFF; \
        *( ((cyg_uint8 *)_data_) + (_off_) + 2 ) = (_val_ >> 16) & 0xFF; \
        *( ((cyg_uint8 *)_data_) + (_off_) + 3 ) = (_val_ >> 24) & 0xFF; \
    } while (0)

#define SET_BYTES(_data_, _var_, _size_, _off_) \
    memcpy((void *)(((cyg_uint8 *)_data_)+(_off_)), (void *)(_var_), _size_)

// -------------------------------------------------------------------------
// FAT table entries types 

#define TENTRY_REGULAR  0 // Used when entry points to next file cluster 
#define TENTRY_FREE     1 // Free cluster
#define TENTRY_LAST     2 // Last cluster of file 
#define TENTRY_RESERVED 3 // Reserved cluster
#define TENTRY_BAD      4 // Bad cluster 

// -------------------------------------------------------------------------
// FAT table structures size 

#define DENTRY_SIZE 0x20 // Dir entry size

// -------------------------------------------------------------------------
// Time & date defines 

#define JD_1_JAN_1970 2440588 // 1 Jan 1970 in Julian day number

// -------------------------------------------------------------------------
// Code tracing defines 

#ifdef FATFS_TRACE_DIR_ENTRY
# define TDE 1
#else
# define TDE 0
#endif

#ifdef FATFS_TRACE_CLUSTER
# define TCL 1
#else
# define TCL 0
#endif

#ifdef FATFS_TRACE_DATA
# define TDO 1
#else
# define TDO 0
#endif
    
//==========================================================================
// FAT structures 

// -------------------------------------------------------------------------
// FAT table boot record structure 
   
typedef struct fat_boot_record_s
{
    cyg_uint16    jump;           // 00h : Jump code
//  cyg_uint8     jump0;          //                 + NOP
    char          oem_name[8+1];  // 03h : OEM name
    cyg_uint16    bytes_per_sec;  // 0Bh : cyg_bytes per sector
    cyg_uint8     sec_per_clu;    // 0Dh : Sectors per cluster
    cyg_uint16    res_sec_num;    // 0Eh : Number of reserved sectors
    cyg_uint8     fat_tbls_num;   // 10h : Number of copies of fat
    cyg_uint16    max_root_dents; // 11h : Maximum number of root dir entries
    cyg_uint16    sec_num_32;     // 13h : Number of sectors in partition < 32MB
    cyg_uint8     media_desc;     // 15h : Media descriptor
    cyg_uint16    sec_per_fat;    // 16h : Sectors per FAT
    cyg_uint16    sec_per_track;  // 18h : Sectors per track
    cyg_uint16    heads_num;      // 1Ah : Number of heads
    cyg_uint32    hsec_num;       // 1Ch : Number of hidden sectors
    cyg_uint32    sec_num;        // 20h : Number of sectors in partition
    cyg_uint8     exe_marker[2];  // 1FEh: Executable marker (55h AAh)

// FAT32 specific fields
 
    cyg_uint32    sec_per_fat_32; // 24h : Sectors per FAT
    cyg_uint16    ext_flags;      // 28h : Flags
    cyg_uint16    fs_ver;         // 2Ah : FS version
    cyg_uint32    root_cluster;   // 2Ch : Root dir cluster
    cyg_uint16    fs_info_sec;    // 30h : Sector number of FSINFO structure
    cyg_uint16    bk_boot_sec;    // 32h : Sector number of backup boot record
//  cyg_uint8     reserved[12];   // 34h : Reserved

// Fields with different locations on FAT12/16 and FAT32 
        
    cyg_uint8     drv_num;        // 24h (40h) : Drive number of partition 
//  cyg_uint8     reserved1;      // 25h (41h) : Reserved 1
    cyg_uint8     ext_sig;        // 26h (42h) : Extended signature
    cyg_uint32    ser_num;        // 27h (43h) : Serial number of partition
    char          vol_name[11+1]; // 2Bh (47h) : Volume name of partition
    char          fat_name[8+1];  // 36h (52h) : FAT name
   
} fat_boot_record_t;

// -------------------------------------------------------------------------
// FAT dir entry structure 
#pragma pack(1) 
typedef struct fat_raw_short_dir_entry_s
{
    char       name[8+1];   // 00h : Name
    char       ext[3+1];    // 08h : Extension
    cyg_uint8  attr;        // 0Bh : Attribute
    cyg_uint8  nt_reserved; // 0Ch : Win NT Reserved field
    cyg_uint8  crt_sec_100; // 0Dh : Creation time ms stamp 0 - 199
    cyg_uint16 crt_time;    // 0Eh : Creation time
    cyg_uint16 crt_date;    // 10h : Creation date
    cyg_uint16 acc_date;    // 12h : Last access date
    cyg_uint16 cluster_HI;  // 14h : Starting cluster HI WORD (FAT32)
    cyg_uint16 wrt_time;    // 16h : Time    
    cyg_uint16 wrt_date;    // 18h : Date
    cyg_uint16 cluster;     // 1Ah : Starting cluster 
    cyg_uint32 size;        // 1Ch : Size of the file    
} fat_raw_short_dir_entry_t;

typedef struct fat_raw_long_dir_entry_s
{
	 cyg_uint8           LDIR_Ord;
	 cyg_uint16          LDIR_Name1[5];
	 cyg_uint16        reserved;
	 cyg_uint8          attr;
	 cyg_uint8          LDIR_Type;
	 cyg_uint8          LDIR_Chksum;
	 cyg_uint16          LDIR_Name2[6];
	 unsigned short   LDIR_FstClusLO;
 	cyg_uint16                  LDIR_Name3[2];
}fat_raw_long_dir_entry_t;
#pragma pack(0)
// -------------------------------------------------------------------------
// FAT cluster opts 
 
typedef enum cluster_opts_e
{
    CO_NONE       = 0x00, // NULL option
    CO_EXTEND     = 0x01, // Extend cluster chain if one cluster too short
    CO_ERASE_NEW  = 0x02, // Erase newly allocated cluster
    CO_MARK_LAST  = 0x04  // Mark  newly allocated cluster as last
} cluster_opts_t;

//==========================================================================
// Utility functions 

// -------------------------------------------------------------------------
// get_val_log2()
// Gets the log2 of given value or returns 0 if value is not a power of 2. 
 
static cyg_uint32 
get_val_log2(cyg_uint32 val)
{
    cyg_uint32 i, log2;
    
    i    = val;
    log2 = 0;
    
    while (0 == (i & 1))
    {
        i >>= 1;
        log2++;
    }

    if (i != 1) return 0;
    else        return log2;
}
static cyg_uint8 fatfs_chksum(cyg_uint8 *pFcbname)
{
	short fcbname_len=0,pos=0;
	cyg_uint8 sum,flag;
	sum=0;
	flag=0;
	cyg_uint8 fs_name[11];
	cyg_uint8 *p;
	p=fs_name;
	for(fcbname_len=0;fcbname_len<8;fcbname_len++)
	{
		if((pFcbname[fcbname_len]=='.'||pFcbname[fcbname_len]==0)&&
			                                                                                     flag==0)
		{
			flag=1;
			pos=fcbname_len;
		}
		if(flag==1)
		{
			fs_name[fcbname_len]=' ';
		}
		else
		{
			fs_name[fcbname_len]=pFcbname[fcbname_len];
		}
	}
	if(pFcbname[pos]==0)
	{
		flag=1;
	}
	else
	{
		flag=0;
	}
	for(fcbname_len=8;fcbname_len<11;fcbname_len++)
	{
		if(pFcbname[fcbname_len]==0&&flag==0)
		{
			flag=1;
		}
		if(flag==1)
		{
			fs_name[fcbname_len]=' ';
		}
		if(pFcbname[fcbname_len]!='.'&& flag==0)
		{
			fs_name[fcbname_len]=pFcbname[fcbname_len];
		}
	}
	for(fcbname_len=0;fcbname_len<11;fcbname_len++)
	{
	        fs_name[fcbname_len]=toupper(fs_name[fcbname_len]);
	}
	for(fcbname_len=11;fcbname_len!=0;fcbname_len--)
	{
		sum=((sum&1)?0x80:0) +(sum>>1) + *p++;
	}
	return sum;
}


// -------------------------------------------------------------------------
// cluster_to_block_pos()
// Converts cluster position to blib block position.

static void
cluster_to_block_pos(fatfs_disk_t *disk,
                     cyg_uint32    cluster,
                     cyg_uint32    cluster_pos,
                     cyg_uint32   *block, 
                     cyg_uint32   *block_pos)
{
    cyg_uint32 block_size      = cyg_blib_get_block_size(&disk->blib);
    cyg_uint32 block_size_log2 = cyg_blib_get_block_size_log2(&disk->blib);
    
    *block = (cluster - 2) << (disk->cluster_size_log2 - block_size_log2);
    
    *block_pos = disk->fat_data_pos + cluster_pos;  

    if (*block_pos > block_size)
    {
        *block     += *block_pos >> block_size_log2;
        *block_pos  = *block_pos & (block_size - 1);
    }
}

// -------------------------------------------------------------------------
// disk_write()
// Writes data to disk.

static __inline__ int
disk_write(fatfs_disk_t *disk, 
           void         *buf,
           cyg_uint32   *len,
           cyg_uint32    pos)
{
    return cyg_blib_write(&disk->blib, buf, len, 0, pos);
}

// -------------------------------------------------------------------------
// disk_read()
// Reads data from disk.

static __inline__ int
disk_read(fatfs_disk_t *disk, 
          void         *buf,
          cyg_uint32   *len,
          cyg_uint32    pos)
{
    return cyg_blib_read(&disk->blib, buf, len, 0, pos);
}
//------------------
// disk_cluster_write()
// Writes data to disk at specified cluster position.

static __inline__ int
disk_cluster_write(fatfs_disk_t *disk,
                   void         *buf,
                   cyg_uint32   *len,
                   cyg_uint32    cluster,
                   cyg_uint32    cluster_pos)
{
    cyg_uint32 block, block_pos;

    cluster_to_block_pos(disk, cluster, cluster_pos, &block, &block_pos);

    return cyg_blib_write(&disk->blib, buf, len, block, block_pos);
}

// -------------------------------------------------------------------------
// disk_cluster_read()
// Reads data from disk at specified cluster position.

static __inline__ int
disk_cluster_read(fatfs_disk_t *disk,
                  void         *buf,
                  cyg_uint32   *len,
                  cyg_uint32    cluster,
                  cyg_uint32    cluster_pos)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -