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

📄 fs2.c

📁 支持nvram盘
💻 C
📖 第 1 页 / 共 5 页
字号:
/*** BeginHeader */
#ifndef __FS2_LIB
#define __FS2_LIB
/*** EndHeader */
/*
 * fs2.lib
 *
 * Copyright (C) Z-World, Inc. All rights reserved.
 *
 * Filesystem Mk II
 *
 * Testing note:
 *   The symbol __TESTENV__ should only be defined in the
 *   test harness environment.
 *
 */

/* START LIBRARY DESCRIPTION *********************************************
FILESYSTEM.LIB
	Copyright (c) 2001, ZWorld.

DESCRIPTION:
	Filesystem Mk II.

	This an a (mostly) API-compatible replacement for FILESYSTEM.LIB.
	This library should be used for new code.

END DESCRIPTION **********************************************************/

/*** BeginHeader _fs */

#use "errno.lib"
#ifndef __TESTENV__
	#define TRACE(x)
	//#define TRACE(x) do { if (_fs.trap) printf x; } while(0)
#else
	// We need to rename some of the API functions so they don't
	// conflict with <stdio.h>.  They should be referred to as
	// the fs_* version when called from __TESTENV__ test harness.
	// (These are undef'd at end)
	#define fclose fs_close
	#define fflush fs_flush
	#define fread fs_read
	#define fwrite fs_write
	#define fseek fs_seek
	#define ftell fs_tell
	extern int t_trace;	// Runtime trace
	#define TRACE(x) do { if (t_trace) printf x; } while(0)
#endif

#ifndef fs_nodebug
	#define fs_nodebug nodebug
#endif

/*
 * Default values for compile-time options
 */
#ifndef FS2_USE_PROGRAM_FLASH
	#define FS2_USE_PROGRAM_FLASH 0		// Default to not using the 1st (program) flash.
#endif

#ifndef FS_MAX_DEVICES
  #if (FS2_USE_PROGRAM_FLASH > 0 && XMEM_RESERVE_SIZE > 0)
    #if (FS2_RAM_RESERVE > 0)
      #define FS_MAX_DEVICES		3		// Maximum physical media
    #else
      #define FS_MAX_DEVICES		2
    #endif
  #else
    #if (FS2_RAM_RESERVE > 0)
      #define FS_MAX_DEVICES		2
    #else
      #define FS_MAX_DEVICES		1
    #endif
  #endif
#endif

#ifndef FS_MAX_LX
  #define FS_MAX_LX			FS_MAX_DEVICES		// Maximum logical extents
#endif

#ifndef FS_MAX_FILES
  #define FS_MAX_FILES			6		// Maximum files in filesystem
#endif

#ifndef FS_MAX_LS_PER_PS
  #define FS_MAX_LS_PER_PS		64		// Max LS per PS of any LX.
#endif

#ifndef FS_MIN_PBUF_SIZE
	// This must be a power of 2 between 64 and 8192 inclusive.
  #define FS_MIN_PBUF_SIZE		256	// Min physical sector buffer size
#endif

#define FS_DEFAULT_FLASH_SHIFT	10	// Default LS size of 1K for flash
#define FS_DEFAULT_RAM_SHIFT		7	// Default LS size of 128 bytes for RAM

/*
 * Basic typedefs
 */


typedef word FileNumber;		// External file numbers (for API) - contains file number
										// in low byte, LX number in high byte.

// Block identifier; first byte of structures stored in filesystem (*-blocks).
typedef byte FSmagic;
#define FSMAGIC_F		0xFF		// Free block.  This must be 0xFF to correspond to erased h/w
#define FSMAGIC_B		0x7F		// B-block (header for file data per LS)
#define FSMAGIC_H		0xFE		// H-block (header for file metadata per LS)
#define FSMAGIC_DEL	(FSMAGIC_B & FSMAGIC_H)		// A B- or H-block marked as deleted (BW devices)
#define FSMAGIC_W		0x18		// Wear-leveling unit header
#define FSMAGIC_BAD	0x00		// Bad block (do not re-use)

// File attribute bits: Reserved (not yet implemented)
typedef byte FSattrs;
#define FSATTR_BIN	0x80		// Binary (else cannot contain 0xFF chars)
#define FSATTR_NOLOG 0x40		// No automatic logging (else all updates logged)
#define FSATTR_APONLY 0x20		// Append-only (else overwritable)

// Device classes
typedef byte FSdevclass;
#define FSDC_SSW		0x01		// Small-sector writable flash
#define FSDC_BW		0x02		// Byte-writable (AND over existing data) flash
#define FSDC_NVRAM	0x03		// Battery-backed SRAM

// Types used in *-block fields
typedef long FSwear;				// Wear (erase) counter
typedef word FSrwear;			// Relative wear counter
typedef byte FSwlocount;		// Wear-leveling operation count
typedef long FSversion;			// LS rewrite counter per file/metadata.  Starts at 1.
typedef word FSseq;				// LS sequence number within file
typedef byte FSfilenum;			// File number within LX
typedef byte FSEFnum;			// Existing file index (filesystem-wide)
typedef byte FSLXnum;			// Logical extent (LX) number
typedef word FSoffset;			// Offset of byte (or count) within LS
typedef word FSLSnum;			// Logical sector (LS) number or counter
typedef word FSPSnum;			// Physical sector (PS) number or counter
typedef word FSchecksum;		// Checksum value.  Checksums are computed using 1's complement
										// addition of 16-bit words.  Where necessary, odd byte counts
										// are padded with assumed zeros.  The checksum is stored as its
										// 1's complement, with 0xFFFF stored as 0x0000 (0xFFFF in a checksum
										// field indicates the checksum was not written).  Thus, if the
										// checksum field itself is included in the verification, then the
										// result of a valid checksum will be 0xFFFF or 0x0000.

// 'whence' parameter values for fseek().
#define SEEK_SET		0
#define SEEK_CUR		1
#define SEEK_END		2
#define SEEK_RAW		3

// 'flags' bits for fsck().
#define FSCK_HEADERS		0x0001
#define FSCK_CHECKSUMS	0x0002
#define FSCK_VERSION		0x0004

// 'command' values for fs_setup().
#define FS_MODIFY_EXTENT 1
#define FS_PARTITION_FRACTION 2

#define FS_INVALID_LS ((FSLSnum)(-1))	// End of chain marker etc.
#define FS_INVALID_CHK ((FSchecksum)(-1))	// Checksum not written.

// *-block definitions.  All must be even size unless noted otherwise.

// Wear-leveling unit header.  Note that dummy W-blocks (used when LS size < PS size)
// are set to all 0xFF.
typedef struct {
	FSmagic		magic;		// FSMAGIC_W
	FSwlocount	wlo_num;		// Wear-leveling operation counter
	FSrwear		rwear;		// Wear since last WLO
	FSwear		wear;			// Total wear (erase or rewrite count)
} FS_w;

typedef struct {
	FS_w			w;
	FSmagic		magic;
} FS_w_aug;						// W-block augmented with following block's magic ID.

typedef struct {
	FSmagic		magic;		// FSMAGIC_B
	FSfilenum	filenum;		// File name
	FSseq			seq;			// Sequence within file
	FSversion	version;		// Version within file
#ifdef __TESTENV__
	short			pad;			// Pad to force chksum to be last bytes in struct
#endif
	FSchecksum	chksum;		// ~Checksum of this B-block and preceding W-block (if any)
} FS_b;

typedef struct {
	FSmagic		magic;		//
	FSfilenum	filenum;		// These 4 fields must match definition in FS_b.
	FSseq			seq;			//
	FSversion	version;		//
	
	FSLXnum		lxn;			// LX number of data
	FSattrs		attrs;		// File attributes (reserved)
	FSoffset		first_offs;	// Offset of start of data in first data LS
	FSseq			first_seq;	// Sequence number of first data LS
	FSoffset		last_offs;	// Offset of next free byte in last data LS
	FSchecksum	last_chk;	// Checksum of last data LS
	
	FSchecksum	chksum;		// ~Checksum of this H-block and preceding W-block (if any)
} FS_h;

typedef struct {
	FSoffset		new_offs;	// New offset in last (append) or first (shift) LS.  Only the 13 LSBs
									// contain the offset, the high 3 bits contain the log entry type.
#define FS_OFFS_MASK	0x1FFF	// Mask for bits in the above corresponding to offset
#define FS_LOG_DEL	0x8000	// This bit marks entry as deletion (shift) entry, otherwise append:
										// Allows proper interpretation of the log_data field.
	FSchecksum	log_data;	// New last LS checksum (append) or first data sequence number (shift).
	FSchecksum	log_chk;		// ~Checksum of this log entry.
} FS_l;



// Structures maintained at run-time only.

// Existing file descriptor
typedef struct {
	short			in_use;			// Flag indicating entry in use.  0 if this EF not in use.
	FSfilenum	name;				// Corresponding file number
	FSLXnum		metalx;			// Metadata LX number
	FSLXnum		datalx;			// Data LX number
	FSattrs		attrs;			// File attributes (fixed once created).
	FSLSnum		first_mls;		// First LS in metadata LX chain
	FSLSnum		first_dls;		// First LS in data LX chain
	FSLSnum		num_mls;			// Number of metadata LSs in chain (0 or 1)
	FSLSnum		num_dls;			// Number of data LSs in chain
	FSseq			first_seq;		// Sequence number of first LS (0 unless shifted)
	FSversion	vers;				// Highest current LS version number
	short			ref_count;		// Number of times this file currently opened
	
	FSoffset		first_offs;		// Offset of start of data in first LS [0..datalx->d_size-1]
	FSoffset		m_offs;			// Offset of where to add next metadata log (L-block).
	FSoffset		d_offs;			// Offset of EOF in last LS.
	FSchecksum	data_chk;		// Checksum of last data LS (not 1's complement; it accumulates).
	long			eof;				// Position of EOF = length of file.
} FS_ef;



// Logical extent descriptor (LXD)
typedef struct FS_lxd_t {
	// Following fields set up _before_ calling fs_init()...
	// Can mostly be filled in by gflash_init() or nvram_init() in FS_DEV.LIB
	long			dev_offs;	// Device offset of start of LX (usually 0)
										// !!! do not change offset of above fields !!!
	FSdevclass	dev_class;	// Device class of the device containing this LX
	byte			dev_index;	// Device number
	short		ls_shift;		// Log2(ls_size) 6 to 13 inclusive.
	long			ps_size;		// Minimum 32, power of 2 if <= ls_size, else multiple of ls_size up
									// to a maximum of FS_MAX_LS_PER_PS times ls_size.
	word		num_ps;		// Number of PSs in this LX (1..32768)
	void *		data;			// Data specific to low-level driver
	byte			wear_leveling;	// Whether to do wear-leveling (usually 1 for flash)
	byte			dummy_lx;	// Whether filesystem is to reserve this LX
	// Device methods.  See documentation for implementing low-level drivers.
#ifdef __TESTENV__
	char *		(*map)(struct FS_lxd_t * lxd, long dev_rel);
	short			(*andover)(struct FS_lxd_t * lxd, long src_phy, word len, char * dest);
	short			(*erase)(struct FS_lxd_t * lxd, char * dest_ps_start);
	short			(*write)(struct FS_lxd_t * lxd, long src_phy, word len, char * dest);
	short			(*init)(struct FS_lxd_t * lxd);
	short			(*flush)(struct FS_lxd_t * lxd);
#else
	char *		(*map)();
	short			(*andover)();
	short			(*erase)();
	short			(*write)();
	short			(*init)();
	short			(*flush)();
#endif
	// ...end of application-initialized fields.
	
	// Following fields set up by fs_init()...
	FSLXnum		this;					// This LX number
	word			id;					// Flash ID (if relevant)
	word			ps_per_ls;			// Number of PSs per LS, 0 if ps_size==0 or PS>LS
	word			ls_size;				// Power of 2 between 64 and 8192 inclusive
	FSLSnum		num_ls;				// Number of LSs (1..32768)
	word			ls_per_ps;			// Number of LSs per PS, 0 if PS<LS
	word			d_size;				// Size of data block in LS ( < ls_size)
	FSwlocount	high_wlo;			// Highest WLO count observed.
	
	long /* FSLSnum* */	lstab;	// Phys addr of LS table, num_ls entries.  Each lstab entry
											// is the index of the next LS in a logical chain.  Chains
											// exist for free LSs, file data and file metadata.  The
											// end of a chain is marked with a value of 0xFFFF.  The
											// table exists in xmem, but the 2-byte values make access
											// via LDP convenient.
	FSLSnum		first_free;			// First free (ready-to-use) entry
	FSLSnum		num_free;			// Number of free LSs
	FSLSnum		first_deleted;		// First deleted entry.  These are generated when LSs are marked as
											// deleted without actual erasure.  They are not yet ready for use.
	FSLSnum		num_deleted;		// Number of deleted LSs: Non-zero only for BW devices.
	FSLSnum		first_bad;			// First bad block
	FSLSnum		num_bad;				// Number of bad blocks
	FSLSnum		min_free;			// For BW only, the minimum number of "emergency" free LSs to
											// keep aside for the purpose of recycling del LSs.  Defaults to
											// ls_per_ps - 1.
} FS_lxd;


// This is the top-level structure for the entire filesystem.  There is one
// instance of this struct, in the static variable _fs.  This makes the
// filesystem non-reentrant.
typedef struct {
	// Following fields set up _before_ calling fs_init().  This is done by global init.
	FSLXnum		num_lx;			// Number of valid logical extents [1..FS_MAX_LS].
	FS_lxd		lx[FS_MAX_LX+1];	// Logical extents.  Note that the 0th (first) entry is
					// not used (except maybe as a cache to avoid array
					// indexing operations).  Some of this is further filled in by fs_init().
	FSLXnum		flash_lx;		// Preferred flash LX number.  This is the 2nd flash if available,
							// otherwise is the program flash, or 0 if no flash available.
	FSLXnum		ram_lx;		// RAM LX number, or zero if not available.
	FSLXnum		other_lx;	// If 2nd flash is "preferred", this will indicate the non-preferred
							// flash (normally the program flash, if available).  0 if no other
							// flash available.
		
	// Following fields set up by fs_init().
	FSLXnum		cur_meta;		// Current default metadata LX number
	FSLXnum		cur_data;		// ...and data
		
	unsigned char	init;				// True if in process of init. or formatting entire FS.
	FSLXnum		cur_fmt;			// The LX currently being formatted.
	
//#define FS_MAX_FILENUM (1<<sizeof(FSfilenum)*8)
#define FS_MAX_FILENUM	256
	FSEFnum		eftab[FS_MAX_FILENUM+1];	// File number to EF mapping.  Zero entry if file does
										// not exist.  Indexes into the ef array below.
	
	FS_ef		ef[FS_MAX_FILES+1];	// Existing file information.  0th entry not used except
											// as cache.
	
	unsigned short pbuf_size;			// Allocated size of the following (max 8k)
	long			pbuf;				// paddr of physical sector buffer.  This is enough for
											// the largest PS size in any SSW LX, or the largest LS
											// size in any BW LX.
	int			trap;					// Flag for runtime debugging
	int			setup_failed;		// Non-zero if an error occurred in fs_init premain.
} FS_universe;

extern FS_universe _fs;			// The global variable to access it.
extern byte _fs_savexpc;		// Register save areas for asm routines
extern byte _fs_savexpc2;
extern byte _fs_savemb1cr;
extern long _fs_pbuf;

/*
 * High-level API
 */
typedef struct
{
	FSfilenum	name;				// Name, or 0 if not open.
	FS_ef *		ef;				// Cached pointers to useful info
	FS_lxd *		mlxd;
	FS_lxd *		dlxd;
	byte			mode;
#define FSMODE_RO		0x01		// Read-ony (else read/write)
#define FSMODE_RAW	0x02		// Raw reads i.e. past EOF up to end of last LS.

	long			position;		// Current read/write position
	
} File;
	
/*** EndHeader */

FS_universe _fs;
byte _fs_savexpc;
byte _fs_savexpc2;
byte _fs_savemb1cr;
long _fs_pbuf;


/*** BeginHeader fs_lstabent, fs_set_lstabent, fs_checksum, fs_checksum_x */
// fs_erase_chain halt condition flags
#define FSHALT_COUNT		0x0001	// Erase a maximum of max_count
#define FSHALT_SEQ		0x0002	// Erase only while LS sequence == while_seq
#define FS_REALLY_ERASE	0x0004	// Really erase sectors of SSW device

#define FS_FQFN(lxn, name) ((FileNumber)((name) + ((lxn)<<8)))
#define FS_SPLITFN(name, lxn, fnum) (lxn = (name)>>8, fnum = (name)&0xFF)
#define FS_EXISTS(name) (_fs.eftab[name] != 0)
#define FS_METALX_OF_FILE(name) (_fs.ef[_fs.eftab[name]].metalx)
#define FS_DATALX_OF_FILE(name) (_fs.ef[_fs.eftab[name]].datalx)
#define FS_EF_OF_FILE(name) (_fs.ef + _fs.eftab[name])
#define FS_IS_DUMMY_LX(lxn) (_fs.lx[lxn].dummy_lx)
#define FS_IS_VALID_LX(lxn) ((lxn) >= 1 && (lxn) <= _fs.num_lx && !FS_IS_DUMMY_LX(lxn))
#define FS_INIT_LOGOFFS (sizeof(FS_h) - sizeof(FS_b))

#define FS_IS_SSW(lxd) (lxd->dev_class == FSDC_SSW)
#define FS_IS_BW(lxd) (lxd->dev_class == FSDC_BW)
#define FS_IS_RAM(lxd) (lxd->dev_class == FSDC_NVRAM)
#define FS_LXN2PTR(lxn) (_fs.lx + (lxn))
#define FS_PTR2LXN(lxd) ((lxd)->this)
#define FS_LS2OFFSET(lxd, ls) ((long)(ls) << lxd->ls_shift)
#define FS_PS2OFFSET(lxd, ps) ((long)(ps) * lxd->ps_size)
#define FS_LS2PS(lxd, ls) (((long)(ls) << lxd->ls_shift) / lxd->ps_size)
#ifndef __TESTENV__
#define FS_SAVE_XPC \
	ld		a,xpc	$\
	ld		(_fs_savexpc),a $\
	ld		a,(MB1CRShadow) $\
	ld		(_fs_savemb1cr),a
#define FS_SAVE_XPC2 \
	ld		a,xpc	$\
	ld		(_fs_savexpc2),a
#define FS_RESTORE_XPC \
	ld		a,(_fs_savemb1cr) $\
	ioi ld (MB1CR),a $\
	ld		(MB1CRShadow),a $\
	ld		a,(_fs_savexpc) $\
	ld		xpc,a
#define FS_RESTORE_XPC2 \
	ld		a,(_fs_savexpc2) $\
	ld		xpc,a
#endif
#define FS_CALL_MAP(lxd, devrel) (lxd->map(lxd, (long)(devrel)))

⌨️ 快捷键说明

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