?? nftllite.c
字號:
/*
* $Log: V:/nftllite.c_v $
*
* Rev 1.21 01 Mar 1998 12:59:46 amirban
* Add parameter to mapSector, and use fast-mount procedure
*
* Rev 1.20 23 Feb 1998 17:08:38 Yair
* Added casts
*
* Rev 1.19 23 Nov 1997 17:20:52 Yair
* Get rid of warnings (with Danny)
*
* Rev 1.18 11 Nov 1997 15:26:22 ANDRY
* get rid of compiler warnings
*
* Rev 1.17 10 Sep 1997 16:30:10 danig
* Got rid of generic names
*
* Rev 1.16 04 Sep 1997 16:18:06 danig
* Debug messages
*
* Rev 1.15 31 Aug 1997 15:21:04 danig
* Registration routine return status
*
* Rev 1.14 28 Aug 1997 16:44:46 danig
* Share buffer with MTD
*
* Rev 1.13 21 Aug 1997 14:06:28 unknown
* Unaligned4
*
* Rev 1.12 14 Aug 1997 14:10:42 danig
* Fixed defragment bug
*
* Rev 1.11 28 Jul 1997 14:51:16 danig
* volForCallback
*
* Rev 1.10 24 Jul 1997 17:57:42 amirban
* FAR to FAR0
*
* Rev 1.9 20 Jul 1997 18:27:44 danig
* Initialize vol.flash in formatNFTL
*
* Rev 1.8 07 Jul 1997 15:22:28 amirban
* Ver 2.0
*
* Rev 1.7 29 Jun 1997 17:56:36 danig
* Comments
*
* Rev 1.6 29 Jun 1997 15:00:12 danig
* Fixed formatted size
*
* Rev 1.5 08 Jun 1997 17:02:52 amirban
* SECTOR_USED is default
*
* Rev 1.4 03 Jun 1997 17:08:16 amirban
* setBusy change
*
* Rev 1.3 01 Jun 1997 13:43:40 amirban
* Big-endian & use sector-map caching
*
* Rev 1.2 25 May 1997 17:51:10 danig
* Adjust unitSizeBits so header unit fits in one unit
*
* Rev 1.1 25 May 1997 15:20:46 danig
* Changes to format
*
* Rev 1.0 18 May 1997 17:57:56 amirban
* Initial revision.
*/
/************************************************************************/
/* */
/* FAT-FTL Lite Software Development Kit */
/* Copyright (C) M-Systems Ltd. 1995-1997 */
/* */
/************************************************************************/
#include "tffs/fltl.h"
#include "tffs/flflash.h"
#include "tffs/flbuffer.h"
typedef long int VirtualAddress;
typedef unsigned char PhysUnit;
typedef unsigned short UnitNo;
#define UNASSIGNED_ADDRESS 0xffffffffl
#define UNIT_DATA_OFFSET 8
#define SECTOR_ECC_OFFSET 0
#define SECTOR_DATA_OFFSET 6
#define UNIT_TAILER_OFFSET (SECTOR_SIZE + 8)
#define FOLD_MARK_OFFSET (2 * SECTOR_SIZE + 8)
#define ERASE_MARK 0x3c69
#define MAX_UNIT_CHAIN 20
#define UNIT_FREE 0xff
#define UNIT_AVAILABLE 0x80
#define UNIT_REPLACED 0x40
#define UNIT_COUNT 0x3f
#define UNIT_BAD_ORIGINAL 0
#define UNIT_BAD_MARKED 7
#define NO_UNIT 0xffff
#define REPLACING_UNIT 0x8000
/* Block flags */
#define SECTOR_FREE 0xff
#define SECTOR_USED 0x55
#define SECTOR_IGNORE 0x11
#define SECTOR_DELETED 0x00
#define FOLDING_IN_PROGRESS 0x5555
#define FOLDING_COMPLETE 0x1111
#define ERASE_NOT_IN_PROGRESS -1
/* unit header */
typedef struct {
LEushort virtualUnitNo;
LEushort replacementUnitNo;
LEushort spareVirtualUnitNo;
LEushort spareReplacementUnitNo;
} UnitHeader;
/* erase record */
typedef struct {
LEulong eraseCount;
LEushort eraseMark;
LEushort eraseMark1;
} UnitTailer;
/* Medium Boot Record */
typedef struct {
char bootRecordId[6]; /* = "ANAND" */
LEushort noOfUnits;
LEushort bootUnits;
Unaligned4 virtualMediumSize;
} BootRecord;
#ifndef MALLOC_TFFS
#define HEAP_SIZE (0x100000l / ASSUMED_NFTL_UNIT_SIZE) * \
(sizeof(UnitNo) + sizeof(PhysUnit)) * \
MAX_VOLUME_MBYTES
#endif
struct tTLrec {
FLBoolean badFormat; /* true if TFFS format is bad*/
UnitNo orgUnit, /* Unit no. of boot record */
spareOrgUnit; /* ... and spare copy of it*/
UnitNo freeUnits; /* Free units on media*/
unsigned int erasableBlockSizeBits; /* log2 of erasable block size*/
UnitNo noOfVirtualUnits;
UnitNo noOfTransferUnits;
unsigned long unitOffsetMask; /* = 1 << unitSizeBits - 1 */
unsigned int sectorsPerUnit;
UnitNo noOfUnits,
bootUnits;
unsigned int unitSizeBits;
SectorNo virtualSectors;
UnitNo roverUnit, /* Starting point for allocation search */
countsValid; /* Number of units for which unit
count was set */
PhysUnit *physicalUnits; /* unit table by physical no. */
UnitNo *virtualUnits; /* unit table by logical no. */
SectorNo mappedSectorNo;
const void FAR0 *mappedSector;
CardAddress mappedSectorAddress;
/* Accumulated statistics. */
long int sectorsRead,
sectorsWritten,
sectorsDeleted,
parasiteWrites,
unitsFolded;
FLFlash flash;
FLBuffer *buffer;
#ifndef MALLOC_TFFS
char heap[HEAP_SIZE];
#endif
};
#define nftlBuffer vol.buffer->data
typedef TLrec Anand;
static Anand vols[DRIVES];
/*----------------------------------------------------------------------*/
/* u n i t B a s e A d d r e s s */
/* */
/* Returns the physical address of a unit. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* unitNo : Physical unit number */
/* */
/* Returns: */
/* physical address of unitNo */
/*----------------------------------------------------------------------*/
static CardAddress unitBaseAddress(Anand vol, UnitNo unitNo)
{
return (CardAddress)unitNo << vol.unitSizeBits;
}
/*----------------------------------------------------------------------*/
/* g e t U n i t D a t a */
/* */
/* Get virtual unit No. and replacement unit no. of a unit. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* unitNo : Physical unit number */
/* virtualUnitNo : Receives the virtual unit no. */
/* replacementUnitNo : Receives the replacement unit no. */
/* */
/*----------------------------------------------------------------------*/
static void getUnitData(Anand vol,
UnitNo unitNo,
UnitNo *virtualUnitNo,
UnitNo *replacementUnitNo)
{
UnitHeader unitData;
vol.flash.read(&vol.flash,
unitBaseAddress(&vol,unitNo) + UNIT_DATA_OFFSET,
&unitData,
sizeof(UnitHeader),
EXTRA);
/* Mask out any 1 -> 0 bit faults by or'ing with spare data */
*virtualUnitNo = LE2(unitData.virtualUnitNo) |
LE2(unitData.spareVirtualUnitNo);
*replacementUnitNo = LE2(unitData.replacementUnitNo) |
LE2(unitData.spareReplacementUnitNo);
}
/*----------------------------------------------------------------------*/
/* s e t U n i t D a t a */
/* */
/* Set virtual unit No. and replacement unit no. of a unit. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* unitNo : Physical unit number */
/* virtualUnitNo : Virtual unit no. */
/* replacementUnitNo : Replacement unit no. */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/* */
/*----------------------------------------------------------------------*/
static FLStatus setUnitData(Anand vol,
UnitNo unitNo,
UnitNo virtualUnitNo,
UnitNo replacementUnitNo)
{
UnitHeader unitData;
UnitNo newVirtualUnitNo, newReplacementUnitNo;
toLE2(unitData.virtualUnitNo,virtualUnitNo);
toLE2(unitData.spareVirtualUnitNo,virtualUnitNo);
toLE2(unitData.replacementUnitNo,replacementUnitNo);
toLE2(unitData.spareReplacementUnitNo,replacementUnitNo);
checkStatus(vol.flash.write(&vol.flash,
unitBaseAddress(&vol,unitNo) + UNIT_DATA_OFFSET,
&unitData,
sizeof(UnitHeader),
EXTRA));
/* Verify the new unit data */
getUnitData(&vol,unitNo,&newVirtualUnitNo, &newReplacementUnitNo);
if (virtualUnitNo != newVirtualUnitNo ||
replacementUnitNo != newReplacementUnitNo)
return flWriteFault;
else
return flOK;
}
/*----------------------------------------------------------------------*/
/* g e t N e x t U n i t */
/* */
/* Get next unit in chain. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* unitNo : Physical unit number */
/* */
/* Returns: */
/* Physical unit number of the unit following unitNo in the chain. */
/* If such unit do not exist, return NO_UNIT. */
/*----------------------------------------------------------------------*/
static UnitNo getNextUnit(Anand vol, UnitNo unitNo)
{
UnitNo virtualUnitNo, replacementUnitNo;
if (!(vol.physicalUnits[unitNo] & UNIT_REPLACED))
return NO_UNIT;
getUnitData(&vol,unitNo,&virtualUnitNo,&replacementUnitNo);
return replacementUnitNo;
}
/*----------------------------------------------------------------------*/
/* g e t S e c t o r F l a g s */
/* */
/* Get sector status. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* sectorAddress : Physical address of the sector */
/* */
/* Returns: */
/* Return the OR of the two bytes in the sector status area (the */
/* bytes should contain the same data). */
/*----------------------------------------------------------------------*/
static unsigned char getSectorFlags(Anand vol, CardAddress sectorAddress)
{
unsigned char flags[2];
vol.flash.read(&vol.flash,
sectorAddress + SECTOR_DATA_OFFSET,
&flags,
sizeof flags,
EXTRA);
return flags[0] | flags[1];
}
/*----------------------------------------------------------------------*/
/* v i r t u a l 2 P h y s i c a l */
/* */
/* Translate virtual sector number to physical address. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* sectorNo : Virtual sector number */
/* */
/* Returns: */
/* physical address of sectorNo */
/*----------------------------------------------------------------------*/
static CardAddress virtual2Physical(Anand vol, SectorNo sectorNo)
{
unsigned unitOffset = (sectorNo % vol.sectorsPerUnit) << SECTOR_SIZE_BITS;
CardAddress prevSectorAddress = UNASSIGNED_ADDRESS;
UnitNo unitNo;
/* follow the chain */
for (unitNo = vol.virtualUnits[sectorNo / vol.sectorsPerUnit];
unitNo != NO_UNIT;
unitNo = getNextUnit(&vol,unitNo)) {
CardAddress sectorAddress = unitBaseAddress(&vol,unitNo) + unitOffset;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -