3763 lines
142 KiB
C
3763 lines
142 KiB
C
/*
|
|
* $Log: V:/Flite/archives/TrueFFS5/Src/BLOCKDEV.C_V $
|
|
*
|
|
* Rev 1.43 Apr 15 2002 20:14:20 oris
|
|
* Prevent any change to the flPolicy environment variable. It must be set to FL_DEFAULT_POLICY.
|
|
*
|
|
* Rev 1.42 Apr 15 2002 07:33:56 oris
|
|
* Moved doc2exb functions declaration to blockdev.c
|
|
* Moved bdkCall function declaration to docbdk.h
|
|
* Bug fix - Bad arguments sanity check for FL_MTD_BUS_ACCESS_TYPE.
|
|
* Bug fix - Missing initialization of global variables:
|
|
* - bus access in flSetDocBusRoutine() and flGetDocBusRoutine() and when ENVIRONMENT_VARS compilation flag is not defined.
|
|
* - verify write when ENVIRONMENT_VARS compilation flag is not defined.
|
|
* - All global (for all sockets and volumes) environment variables where not reinitialized after flExit call.
|
|
* - Renamed initEnvVarsDone to initGlobalVarsDone.
|
|
* - Renamed flInitEnvVars() to flInitGlobalVars().
|
|
* Changed flBusConfig environment array to dword variables instead of single byte.
|
|
* Added support for VERIFY_ERASED_SECTOR compilation flag.
|
|
* Placed multi-doc environment variable under the MULTI_DOC compilation flag.
|
|
* VolumeInfo routine - remove warning by placing eraseCyclesPerUnit variable under FL_LOW_LEVEL compilation flag.
|
|
*
|
|
* Rev 1.41 Feb 19 2002 20:58:08 oris
|
|
* Moved include directives to blockdev.h file.
|
|
* Bug fix - findFreeVolume routine did not initialize flfash records of the volume. It caused exception when formatting a DiskOnChip with more then 1 partition.
|
|
* Compilation error missing ifdef EXIT.
|
|
* Convert TL_LEAVE_BINARY_AREA to FL_LEAVE_BINARY_AREA before sending it to the TL.
|
|
* Bug fix - volumeInfo routine might cause exception if osak version or driver version is larger the designated field.
|
|
* use intermediate variable before sending irFlags to otpSize routine.
|
|
*
|
|
* Rev 1.40 Jan 29 2002 20:07:42 oris
|
|
* Added NAMING_CONVENTION prefix and extern "C" for cpp files to all public routines:
|
|
* flSetEnvVolume, flSetEnvSocket , flSetEnvAll , flSetDocBusRoutine , flGetDocBusRoutine, flBuildGeometry , bdCall and flExit
|
|
* Changed LOW_LEVEL compilation flag with FL_LOW_LEVEL to prevent definition clashes.
|
|
* Removed warnings.
|
|
* Moved writeIPL sanity check to MTD level.
|
|
* Removed download operation after writeIPL call (it is now one of the routines parameters).
|
|
* Added sanity check (null pointer passed) to flSetEnvVolume, flSetDocBusRoutine and flGetDocBusRoutine.
|
|
*
|
|
* Rev 1.39 Jan 28 2002 21:23:32 oris
|
|
* Bug fix - initialization of flPolicy variable caused a memory lick (set max unit chain to 0).
|
|
* Changed FL_NFTL_CACHE_ENABLED to FL_TL_CACHE_ENABLED.
|
|
* Changed flSetDocBusRoutine interface and added flGetDocBusRoutine.
|
|
* Added FL_IPL_DOWNLOAD flag to writeIPL routine in order to control whether the IPL will be reloaded after the update.
|
|
*
|
|
* Rev 1.38 Jan 23 2002 23:30:46 oris
|
|
* Added a call to flExit() in case flSuspend was restored to FL_OFF.
|
|
* Moved Alon based DiskOnChip write IPL routine from blockdev, to diskonc.
|
|
* Added sanity check to flCheckVolume() - Make sure irData is NULL and irLength is set to 0.
|
|
*
|
|
* Rev 1.37 Jan 21 2002 20:43:36 oris
|
|
* Bug fix - Missing\bad support for FL_SECTORS_VERIFIED_PER_FOLDING and FL_VERIFY_WRITE_BDTL environment variables.
|
|
*
|
|
* Rev 1.36 Jan 20 2002 20:40:20 oris
|
|
* Improved documentation of bdFormatPhisycalDrive - Added TL_NORMAL_FORMAT flag was added.
|
|
* Removed ifdef NO_PHYSICAL_IO from flGetBPB routine.
|
|
*
|
|
* Rev 1.35 Jan 17 2002 22:56:22 oris
|
|
* Placed docbdk.h under BDK_ACCESS ifdef
|
|
* Added include directive to docsys.h
|
|
* Removed function prototypes from header.
|
|
* Changed FLFlash record in the volume structure into a pointer
|
|
* Added flBusConfig variable and flSetDocBusRoutine() routine for runtime control over memory access routines - under the FL_NO_USE_FUNC definition.
|
|
* Added flSectorsVerfiedPerFolding environment variable was added
|
|
* Added flSuspendMode environment variable was added.
|
|
* Changed flVerifyWrite environment variable : 4 for Disk partitions 3 for Binary and 1 for the rest.
|
|
* Changed flPolicy to be partition specific.
|
|
* Changed flSetEnv() routine was changed into 3 different routines: flSetEnvVolume / flSetEnvSocket / flSetEnvAll
|
|
* Variables types for environment variables were changed to the minimal size needed.
|
|
* Added flInitEnvVars() routine for setting default values to environment variables.
|
|
* Use single FLFlash record for each volume - (change vol.flash to a pointer instead of the record itself).
|
|
* Added \r to all DEBUG_PRINT routines.
|
|
* Removed SINGLE_BUFFER ifdef.
|
|
* Added volume verification after format for faster write performance with FL_OFF.
|
|
* Removed FLFlash parameter to all TL calls (flMount / flFormat / flPreMount )
|
|
* Added support for firmware other then the 3 defaults (getExbInfo additional parameter)
|
|
* Added support for M+ 16MB
|
|
* Added partition parameter to setBusy - Stores current partition in the socket record for the use of lower TrueFFS layers .
|
|
* Changed tffsmin to TFFSMIN
|
|
* Added FL_VERIFY_VOLUME functionNo.
|
|
* Made sure flInit() initializes all sockets and flashes volumes
|
|
* Added flClearQuickMountInfo() routine (FL_CLEAR_QUICK_MOUNT_INFO)
|
|
* readIPL routine now supports all DiskOnChip
|
|
*
|
|
* Rev 1.34 Nov 29 2001 20:53:44 oris
|
|
* Bug fix - flInquireCapabilities() returned bad status for SUPPORT_WRITE_IPL_ROUTINE.
|
|
*
|
|
* Rev 1.33 Nov 21 2001 11:40:44 oris
|
|
* Changed FL_MULTI_DOC_NOT_ACTIVE to FL_OFF, FL_VERIFY_WRITE_MODE to FL_MTD_VERIFY_WRITE , FL_WITHOUT_VERIFY_WRITE to FL_OFF , FL_MARK_DELETE to FL_ON.
|
|
*
|
|
* Rev 1.32 Nov 08 2001 10:44:04 oris
|
|
* Added flVerifyWrite environment variable that controls the verify write mode at run-time.
|
|
* Added support for large DiskOnChip in flBuildGeometry.
|
|
* Remove s/w protection from binary partition.
|
|
* Placed flAbsMount under ABS_READ_WRITE compilation flag.
|
|
*
|
|
* Rev 1.31 Sep 24 2001 18:23:04 oris
|
|
* Removed warnings.
|
|
*
|
|
* Rev 1.30 Sep 15 2001 23:44:22 oris
|
|
* Changed BIG_ENDIAN to FL_BIG_ENDIAN
|
|
*
|
|
* Rev 1.29 Aug 02 2001 20:04:04 oris
|
|
* Added support for 1k IPL for DiskOnChip 2000 TSOP - writeIPL()
|
|
*
|
|
* Rev 1.28 Jul 29 2001 19:14:24 oris
|
|
* Bug fix for TrueFFS internal mutex when using multi-doc and environment variables (when no multi-doc feature is disbaled)
|
|
*
|
|
* Rev 1.27 Jul 13 2001 00:59:28 oris
|
|
* Changed flash lifetime calculation according to specific flash.
|
|
*
|
|
* Rev 1.26 Jun 17 2001 08:16:50 oris
|
|
* Added NO_PHISICAL_IO compilation flag to reduce code size.
|
|
* Added NO_READ_BBT_CODE compilation flag to reduce code size.
|
|
* Changed placeExbByBuffer exbflags argument to word instead of byte to support /empty flag.
|
|
* Deleted redundent #ifdef MULTI_DOC in flInit().
|
|
*
|
|
* Rev 1.25 May 31 2001 18:11:52 oris
|
|
* Removed readBBT routine from under the #ifndef FL_READ_ONLY.
|
|
*
|
|
* Rev 1.24 May 16 2001 21:16:08 oris
|
|
* Changed the Binary state (0,1) of the environment variables to meaningful definitions.
|
|
* Added flMtlDefragMode environment variable.
|
|
* Added the FL_ prefix to the following defines: ON, OFF
|
|
* Bug fix - One of the "ifndef" statement of NO_IPL_CODE was coded as "ifdef"
|
|
* Change "data" named variables to flData to avoid name clashes.
|
|
*
|
|
* Rev 1.23 May 09 2001 00:31:00 oris
|
|
* Added NO_PHYSICAL_IO , NO_IPL_CODE and NO_INQUIRE_CAPABILITY compilation flags to reduce code size.
|
|
*
|
|
* Rev 1.22 May 06 2001 22:41:04 oris
|
|
* Bug fix - flInquireCapabilities routine did not return the correct value when capability was not supported.
|
|
* Added SUPPORT_WRITE_IPL_ROUTIN capability.
|
|
* Removed warnings.
|
|
*
|
|
* Rev 1.21 May 01 2001 17:05:10 oris
|
|
* Bug fix - bad argument check in flSetEnv routine.
|
|
*
|
|
* Rev 1.20 Apr 30 2001 17:57:00 oris
|
|
* Added new environment variable flMarkDeleteOnFlash.
|
|
*
|
|
* Rev 1.19 Apr 24 2001 17:05:38 oris
|
|
* Bug fix flMoutVolume routine return the correct hidden sectors even if high level mount fails.
|
|
* Bug fix Write IPL routine supports Doc2000 TSOP as well as Millennium Plus.
|
|
* Support readBBT new interface.
|
|
*
|
|
* Rev 1.18 Apr 18 2001 20:43:00 oris
|
|
* Added force download call after writing IPL.
|
|
*
|
|
* Rev 1.17 Apr 18 2001 19:14:24 oris
|
|
* Bug fix - binary partition insert and remove key routine no longer stop the place exb proccess.
|
|
*
|
|
* Rev 1.16 Apr 18 2001 09:26:22 oris
|
|
* noOfDrives variable was changed to unsigned. This is a bug fix for vxWorks boot code.
|
|
* Make sure blockdev does not try to mount more volumes then the VOLUMES definition.
|
|
*
|
|
* Rev 1.15 Apr 16 2001 13:02:38 oris
|
|
* Removed warrnings.
|
|
*
|
|
* Rev 1.14 Apr 12 2001 06:48:22 oris
|
|
* Added call to download routine after physical format in order
|
|
* to load new IPL and to initialize new protection information.
|
|
* Removed warnings.
|
|
*
|
|
* Rev 1.13 Apr 03 2001 16:33:10 oris
|
|
* Removed unused variables.
|
|
* Added proper casting in otpSize call.
|
|
*
|
|
* Rev 1.12 Apr 03 2001 14:33:16 oris
|
|
* Bug fix in absRead sectors when reading multiple sectors.
|
|
*
|
|
* Rev 1.11 Apr 01 2001 14:57:58 oris
|
|
* Bug fix in read multiple sectors.
|
|
*
|
|
* Rev 1.10 Mar 28 2001 06:19:12 oris
|
|
* Removed flChangeEnvVar prototype.
|
|
* Left alligned all # directives.
|
|
* Bug fix in flSetEnv ((value !=0)||(value!=1)) => ((value !=0)&&(value!=1)) + downcast for given argument + add return status code
|
|
* Removed unused variables.
|
|
* Remove casting warnnings.
|
|
* Add arg check in bdFormatPhysicalDrive for BDTLPartitionInfo != NULL.
|
|
* Bug fix for absWrite - multi-secotr write should be initialized with zeros to prevent sector found return code.
|
|
* Replaced the numbers in writeProtect routine to defines (moved from ioctl.h to blockdev.h).
|
|
* Add break for mdocp identification in getPhysicalInfo.
|
|
* Added readIPL routine.
|
|
* Added LOG_FILE compilation flag for EDC errors for mdocp.
|
|
* Added initialization of tl table in flInit.
|
|
* flExit mutex bug fix.
|
|
*
|
|
* Rev 1.9 Mar 05 2001 21:00:34 oris
|
|
* Bug fix - initialize exbLen argument in bdFormatVolume.
|
|
* Bug fix - initialize bdtlFp flags fiels in bdFormatVolume.
|
|
* Restored the flExit pragma under __BORLANDC__ compilation flag
|
|
*
|
|
* Rev 1.8 Feb 22 2001 20:21:34 oris
|
|
* Bug fix in flExit with multi-doc release uncreated mutxe.
|
|
*
|
|
* Rev 1.7 Feb 20 2001 15:44:58 oris
|
|
* Bug fix for mutex initialization in flInit.
|
|
*
|
|
* Rev 1.6 Feb 18 2001 23:29:28 oris
|
|
* Bug fix - Added findFreeVolume call in flFormatPhysicalDrive.
|
|
* bug fix - Added partition sanity check in bdcall entrence.
|
|
* bug fix - Increamented pVol before entering loop in flExit.
|
|
*
|
|
* Rev 1.5 Feb 18 2001 14:13:22 oris
|
|
* Restored FL_BACKGROUND.
|
|
* Place bdkCall extern prototype under BDK_ACCESS compilation flag.
|
|
* Changed multiple volume mechanism - Replaced removeVolumeHandles and
|
|
* flConvertDriveHandle routines with flInit + findFreeVolume and changed
|
|
* dismountPhysicalDrive + flEacit to comply.
|
|
* Changed bdcall volume validity check.
|
|
* Added new volume flag VOLUME_ACCUPIED.
|
|
* Moved all the new environment variable (flPolicy,flUseMultiDoc and flMaxUnitChain)
|
|
* from flcustom.c in order to allow backwards competability.
|
|
* Removed globalMutex (for now).
|
|
* Allocate only 1 mutex when multi-doc is registered therfore setBusy takes only 1 mutex .
|
|
* Bug fix - absRead and absWrite add bootSectors to the given sectors.
|
|
* Bug fix - INVALID_VOLUME_HANDLE changed to INVALID_VOLUME_NUMBER.
|
|
* Bug fix - Added (byte FAR1 *) casting in readBBT call.
|
|
* Bug fix - Added (FLCapability FAR2 *) casting in inquire capability call.
|
|
*
|
|
* Rev 1.4 Feb 14 2001 01:51:32 oris
|
|
* Completly revised flInquireCapabilities routine.
|
|
* Added oldFormat flag to flBuildGeometry routine.
|
|
* Remove FL_BACKGROUND compilation flag.
|
|
* Added arg check for flSetEnv + new FL_SET_MAX_CHAIN.
|
|
* Changed FL_COMPLETE_ASAP_POLICY to FL_SET_POLICY.
|
|
* Moved argument check in flFormatPhysicalDrive to fltl.c.
|
|
* Moved readBBT routine inside bdcall.
|
|
* Placed volumeInfo C\H\S data under ABS_READ_WRITE.
|
|
*
|
|
* Rev 1.3 Feb 13 2001 02:10:48 oris
|
|
* Changed flChangeEnvVar routine name to flSetEnv
|
|
*
|
|
* Rev 1.2 Feb 12 2001 11:51:12 oris
|
|
* Added function prototype in begining of the file.
|
|
* Change routine order in the file.
|
|
* Added mutex support for TrueFFS 5.0 partitions while changing bdcall order.
|
|
* flMountVolume returns the number of boot sectors.
|
|
* Moved the writeBBT routine to FLTL.C.
|
|
* Added static before changePassword.
|
|
* Added static before writeProtect.
|
|
* Added static before dismountLowLevel.
|
|
* Added static before writeIPL.
|
|
* Added static before inquireCapabilities.
|
|
* window base is returned by getPhysicalInfo in irLength.
|
|
* Added MULTI_DOC compliation flag.
|
|
*
|
|
* Rev 1.1 Feb 07 2001 17:55:06 oris
|
|
* Buf fix for writeBBT of no bad blocks
|
|
* Moved readBBT routine from under the fl_read_only define
|
|
* Added casting in calls to readBBT and writeBBT
|
|
* Added checkStatus check for flAbsWrite and flAbsRead routines
|
|
* Added initialization of noOfMTDs and noOfSockets in flInit
|
|
*
|
|
* Rev 1.0 Feb 04 2001 18:53:04 oris
|
|
* Initial revision.
|
|
*
|
|
*/
|
|
|
|
|
|
/*************************************************************************/
|
|
/* M-Systems Confidential */
|
|
/* Copyright (C) M-Systems Flash Disk Pioneers Ltd. 1995-2001 */
|
|
/* All Rights Reserved */
|
|
/*************************************************************************/
|
|
/* NOTICE OF M-SYSTEMS OEM */
|
|
/* SOFTWARE LICENSE AGREEMENT */
|
|
/* */
|
|
/* THE USE OF THIS SOFTWARE IS GOVERNED BY A SEPARATE LICENSE */
|
|
/* AGREEMENT BETWEEN THE OEM AND M-SYSTEMS. REFER TO THAT AGREEMENT */
|
|
/* FOR THE SPECIFIC TERMS AND CONDITIONS OF USE, */
|
|
/* OR CONTACT M-SYSTEMS FOR LICENSE ASSISTANCE: */
|
|
/* E-MAIL = info@m-sys.com */
|
|
/*************************************************************************/
|
|
|
|
#include "bddefs.h"
|
|
#include "blockdev.h"
|
|
|
|
#ifdef FL_BACKGROUND
|
|
#include "backgrnd.h"
|
|
#endif
|
|
|
|
|
|
/********************* Extern Function Prototype Start *******************/
|
|
#ifdef WRITE_EXB_IMAGE
|
|
extern FLStatus getExbInfo(Volume vol, void FAR1 * buf, dword bufLen, word exbFlags);
|
|
extern FLStatus placeExbByBuffer(Volume vol, byte FAR1 * buf, dword bufLen,
|
|
word windowBase,word exbFlags);
|
|
#endif /* WRITE_EXB_IMAGE */
|
|
|
|
#if (defined(FORMAT_VOLUME) && defined(COMPRESSION))
|
|
extern FLStatus flFormatZIP(unsigned volNo, TL *baseTL , FLFlash * flash);
|
|
#endif
|
|
#if defined(FILES) && FILES > 0
|
|
extern File fileTable[FILES]; /* the file table */
|
|
extern FLStatus flushBuffer(Volume vol);
|
|
extern FLStatus openFile(Volume vol, IOreq FAR2 *ioreq);
|
|
extern FLStatus closeFile(File *file);
|
|
extern FLStatus joinFile (File *file, IOreq FAR2 *ioreq);
|
|
extern FLStatus splitFile (File *file, IOreq FAR2 *ioreq);
|
|
extern FLStatus readFile(File *file,IOreq FAR2 *ioreq);
|
|
extern FLStatus writeFile(File *file, IOreq FAR2 *ioreq);
|
|
extern FLStatus seekFile(File *file, IOreq FAR2 *ioreq);
|
|
extern FLStatus findFile(Volume vol, File *file, IOreq FAR2 *ioreq);
|
|
extern FLStatus findFirstFile(Volume vol, IOreq FAR2 *ioreq);
|
|
extern FLStatus findNextFile(File *file, IOreq FAR2 *ioreq);
|
|
extern FLStatus getDiskInfo(Volume vol, IOreq FAR2 *ioreq);
|
|
extern FLStatus deleteFile(Volume vol, IOreq FAR2 *ioreq,
|
|
FLBoolean isDirectory);
|
|
extern FLStatus renameFile(Volume vol, IOreq FAR2 *ioreq);
|
|
extern FLStatus makeDir(Volume vol, IOreq FAR2 *ioreq);
|
|
#endif /* FILES > 0 */
|
|
|
|
/********************* Extern Function Prototype End *******************/
|
|
|
|
/********************* Internal Function Prototype Start ***************/
|
|
|
|
void flInitGlobalVars(void);
|
|
|
|
/********************* Internal Function Prototype End *****************/
|
|
|
|
/********************* Global variables Start **************************/
|
|
|
|
Volume vols[VOLUMES];
|
|
FLMutex flMutex[SOCKETS];
|
|
byte handleConversionTable[SOCKETS][MAX_TL_PARTITIONS];
|
|
FLBoolean initDone = FALSE; /* Initialization not done yet */
|
|
FLBoolean initGlobalVarsDone = FALSE; /* Initialization of environment */
|
|
/* and access type variables not */
|
|
/* done yet. */
|
|
unsigned noOfDrives;
|
|
|
|
dword flMsecCounter = 0;
|
|
|
|
/* bus configuration
|
|
*
|
|
* DiskOnChip minimal bus width
|
|
*/
|
|
#ifndef FL_NO_USE_FUNC
|
|
dword flBusConfig[SOCKETS];
|
|
#endif /* FL_NO_USE_FUNC */
|
|
|
|
/* Verify write state
|
|
*
|
|
* BDTL partitions : 0-(MAX_TL_PARTITIONS-1)
|
|
* Binary partitions : MAX_TL_PARTITIONS - (2*MAX_TL_PARTITIONS-2)
|
|
* Last : 2*MAX_TL_PARTITIONS-1
|
|
*/
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
|
|
byte flVerifyWrite[SOCKETS][MAX_TL_PARTITIONS<<1];
|
|
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
|
|
|
|
#ifdef ENVIRONMENT_VARS
|
|
cpyBuffer tffscpy; /* Pointer to memory copy routine */
|
|
cmpBuffer tffscmp; /* Pointer to memory compare routine */
|
|
setBuffer tffsset; /* Pointer to memory set routine */
|
|
|
|
/********************************************/
|
|
/* default values for environment variables */
|
|
/********************************************/
|
|
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
|
|
/* Max sectors verified per write operation (must be even number) */
|
|
dword flSectorsVerifiedPerFolding = 64;
|
|
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
|
|
#ifdef MULTI_DOC
|
|
/* No multi-doc (MTL) */
|
|
byte flUseMultiDoc;
|
|
/* MTL defragmentaion mode (0 - standard) */
|
|
byte flMTLdefragMode;
|
|
#endif /* MULTI_DOC */
|
|
/* Set the TL operation policy */
|
|
byte flPolicy[SOCKETS][MAX_TL_PARTITIONS];
|
|
/* Maximum chain length */
|
|
byte flMaxUnitChain;
|
|
/* Mark the delete sector on the flash */
|
|
byte flMarkDeleteOnFlash;
|
|
/* Read Only mode */
|
|
byte flSuspendMode;
|
|
|
|
/********************* Global variables End *****************************/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l S e t E n v V o l u m e */
|
|
/* */
|
|
/* Change one of TrueFFS environment variables for a specific partition */
|
|
/* */
|
|
/* Note : This routine is used by all other flSetEnv routines. */
|
|
/* In order to effect variables that are common to several */
|
|
/* sockets or volumes use INVALID_VOLUME_NUMBER */
|
|
/* */
|
|
/* Parameters: */
|
|
/* variableType : variable type to cahnge */
|
|
/* socket : Associated socket */
|
|
/* volume : Associated volume (partition) */
|
|
/* value : varaible value */
|
|
/* */
|
|
/* Note: Variables common to al sockets must be addressed using socket */
|
|
/* 0 and volume 0. */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/* prevValue : The previous value of the variable */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus NAMING_CONVENTION flSetEnvVolume(FLEnvVars variableType ,
|
|
byte socket,byte volume ,
|
|
dword value, dword FAR2 *prevValue)
|
|
{
|
|
/* Arg sanity check */
|
|
if(prevValue == NULL)
|
|
{
|
|
DEBUG_PRINT(("ERROR - prevValue argument is NULL.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
switch (variableType) /* Check value argument is a valid mode */
|
|
{
|
|
case FL_SET_MAX_CHAIN:
|
|
if ((value > 31) || (value < 1))
|
|
{
|
|
DEBUG_PRINT(("Debug: Error - Chains length must between 0 and 32.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
break;
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
|
|
case FL_SECTORS_VERIFIED_PER_FOLDING:
|
|
if (value & 1) /* odd number */
|
|
{
|
|
DEBUG_PRINT(("Debug: Error - sector verification numbr must be even.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
break;
|
|
case FL_VERIFY_WRITE_BDTL:
|
|
if ((value != FL_UPS) && (value != FL_OFF) && (value != FL_ON))
|
|
{
|
|
DEBUG_PRINT(("Debug: Error - verify write of BDTL can not accept this value.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
break;
|
|
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
|
|
case FL_SUSPEND_MODE:
|
|
if((value != FL_OFF) &&
|
|
(value != FL_SUSPEND_WRITE) &&
|
|
(value != FL_SUSPEND_IO) )
|
|
{
|
|
DEBUG_PRINT(("Debug: Error - verify write of BDTL can not accept this value.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
break;
|
|
#ifndef FL_NO_USE_FUNC
|
|
case FL_MTD_BUS_ACCESS_TYPE:
|
|
break;
|
|
#endif /* FL_NO_USE_FUNC */
|
|
default:
|
|
if ((value != FL_ON)&&(value!=FL_OFF))
|
|
{
|
|
DEBUG_PRINT(("Debug: Error - Value must be either FL_ON (1) or FL_OFF(0).\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
}
|
|
|
|
switch (variableType) /* Check volume and socket sanity */
|
|
{
|
|
/* Volume specfic variables */
|
|
|
|
case FL_SET_POLICY:
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
|
|
case FL_VERIFY_WRITE_BDTL:
|
|
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
|
|
#ifdef VERIFY_WRITE
|
|
case FL_VERIFY_WRITE_BINARY:
|
|
#endif /* VERIFY_WRITE */
|
|
if (( volume >= MAX_TL_PARTITIONS ) ||
|
|
((variableType == FL_VERIFY_WRITE_BINARY) &&
|
|
(volume == MAX_TL_PARTITIONS - 1 ) ) )
|
|
{
|
|
DEBUG_PRINT(("Debug: Error - No such volume, therefore can not change environment variable.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
if (socket>=SOCKETS)
|
|
{
|
|
DEBUG_PRINT(("Debug: Error - No such socket, therefore can not change environment variable.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
break;
|
|
|
|
/* Socket specfic variables */
|
|
|
|
#ifdef VERIFY_WRITE
|
|
case FL_VERIFY_WRITE_OTHER:
|
|
#endif /* VERIFY_WRITE */
|
|
case FL_MTD_BUS_ACCESS_TYPE:
|
|
if (socket>=SOCKETS)
|
|
{
|
|
DEBUG_PRINT(("Debug: Error - No such socket, therefore can not change environment variable.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
if (volume!=INVALID_VOLUME_NUMBER)
|
|
{
|
|
DEBUG_PRINT(("Debug: Error - This global variable is common to all volumes.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
break;
|
|
|
|
/* Global variables for all sockets and volumes */
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
|
|
case FL_SECTORS_VERIFIED_PER_FOLDING:
|
|
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
|
|
case FL_IS_RAM_CHECK_ENABLED:
|
|
case FL_TL_CACHE_ENABLED:
|
|
case FL_DOC_8BIT_ACCESS:
|
|
case FL_MULTI_DOC_ENABLED:
|
|
case FL_SET_MAX_CHAIN:
|
|
case FL_MARK_DELETE_ON_FLASH:
|
|
case FL_SUSPEND_MODE:
|
|
case FL_MTL_POLICY:
|
|
if ((socket!=INVALID_VOLUME_NUMBER) || (volume!=INVALID_VOLUME_NUMBER))
|
|
{
|
|
DEBUG_PRINT(("Debug: Error - This global variable is common to all sockets and volumes.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
DEBUG_PRINT(("Debug: Unknown variable type.\r\n"));
|
|
return flFeatureNotSupported;
|
|
}
|
|
|
|
/* Make sure environement variables are */
|
|
/* initialized to their default values */
|
|
flInitGlobalVars();
|
|
|
|
|
|
/***************************************************/
|
|
/* Arguments have been checked now change variable */
|
|
/* and report the previous value. */
|
|
/***************************************************/
|
|
|
|
switch (variableType)
|
|
{
|
|
case FL_IS_RAM_CHECK_ENABLED:
|
|
*prevValue = (dword)flUseisRAM;
|
|
flUseisRAM = (byte)value;
|
|
break;
|
|
case FL_TL_CACHE_ENABLED:
|
|
*prevValue = (dword)flUseNFTLCache;
|
|
flUseNFTLCache = (byte)value;
|
|
break;
|
|
case FL_DOC_8BIT_ACCESS:
|
|
*prevValue = (dword)flUse8Bit;
|
|
flUse8Bit = (byte)value;
|
|
break;
|
|
case FL_SET_MAX_CHAIN:
|
|
*prevValue = (dword)flMaxUnitChain;
|
|
flMaxUnitChain = (byte)value;
|
|
break;
|
|
case FL_MARK_DELETE_ON_FLASH:
|
|
*prevValue = (dword)flMarkDeleteOnFlash;
|
|
flMarkDeleteOnFlash = (byte)value;
|
|
break;
|
|
#ifdef MULTI_DOC
|
|
case FL_MULTI_DOC_ENABLED:
|
|
*prevValue = (dword)flUseMultiDoc;
|
|
flUseMultiDoc = (byte)value;
|
|
break;
|
|
case FL_MTL_POLICY:
|
|
*prevValue = (dword)flMTLdefragMode;
|
|
flMTLdefragMode = (byte)value;
|
|
break;
|
|
#endif /* MULTI_DOC */
|
|
case FL_SUSPEND_MODE:
|
|
if((value == FL_OFF) && (flSuspendMode != FL_OFF))
|
|
#ifdef EXIT
|
|
flExit();
|
|
#endif /* EXIT */
|
|
*prevValue = (dword)flSuspendMode;
|
|
flSuspendMode = (byte)value;
|
|
break;
|
|
case FL_SET_POLICY:
|
|
*prevValue = (dword)flPolicy[socket][volume];
|
|
/* flPolicy[socket][volume] = (byte)value; */
|
|
break;
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
|
|
case FL_SECTORS_VERIFIED_PER_FOLDING:
|
|
*prevValue = flSectorsVerifiedPerFolding;
|
|
flSectorsVerifiedPerFolding = value;
|
|
break;
|
|
case FL_VERIFY_WRITE_BDTL:
|
|
*prevValue = (dword)flVerifyWrite[socket][volume];
|
|
flVerifyWrite[socket][volume] = (byte)value;
|
|
break;
|
|
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
|
|
#ifdef VERIFY_WRITE
|
|
case FL_VERIFY_WRITE_BINARY:
|
|
*prevValue = (dword)flVerifyWrite[socket][volume+MAX_TL_PARTITIONS];
|
|
flVerifyWrite[socket][volume+MAX_TL_PARTITIONS] = (byte)value;
|
|
break;
|
|
case FL_VERIFY_WRITE_OTHER:
|
|
*prevValue = (dword)flVerifyWrite[socket][(MAX_TL_PARTITIONS<<1)-1];
|
|
flVerifyWrite[socket][(MAX_TL_PARTITIONS<<1)-1] = (byte)value;
|
|
break;
|
|
#endif /* VERIFY_WRITE */
|
|
|
|
default: /* FL_MTD_BUS_ACCESS_TYPE */
|
|
#ifndef FL_NO_USE_FUNC
|
|
*prevValue = flBusConfig[socket];
|
|
flBusConfig[socket] = (dword)value;
|
|
#endif /* FL_NO_USE_FUNC */
|
|
break;
|
|
}
|
|
return flOK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l S e t E n v S o c k e t */
|
|
/* */
|
|
/* Change one of TrueFFS environment variables for a specific sockets. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* variableType : variable type to cahnge */
|
|
/* socket : socket number */
|
|
/* value : varaible value */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/* prevValue : The previous value of the variable */
|
|
/* if there are more then 1 partition in that */
|
|
/* socket , the first partition value is returned*/
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus NAMING_CONVENTION flSetEnvSocket(FLEnvVars variableType , byte socket , dword value, dword FAR2 *prevValue)
|
|
{
|
|
FLStatus status = flOK;
|
|
byte volume = 0;
|
|
|
|
switch (variableType) /* Check volume and socket sanity */
|
|
{
|
|
/* Volume specific variables */
|
|
|
|
case FL_SET_POLICY:
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
|
|
case FL_VERIFY_WRITE_BDTL:
|
|
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
|
|
status = flSetEnvVolume(variableType,socket,MAX_TL_PARTITIONS-1,value,prevValue);
|
|
#ifdef VERIFY_WRITE
|
|
case FL_VERIFY_WRITE_BINARY:
|
|
#endif /* VERIFY_WRITE */
|
|
for (;(volume<MAX_TL_PARTITIONS-1)&&(status == flOK);volume++)
|
|
status = flSetEnvVolume(variableType,socket,volume,value,prevValue);
|
|
break;
|
|
|
|
/* Socket specific variables */
|
|
|
|
#ifdef VERIFY_WRITE
|
|
case FL_VERIFY_WRITE_OTHER:
|
|
#endif /* VERIFY_WRITE */
|
|
#ifndef FL_NO_USE_FUNC
|
|
case FL_MTD_BUS_ACCESS_TYPE:
|
|
#endif /* FL_NO_USE_FUNC */
|
|
#if (defined(VERIFY_WRITE) || !defined(FL_NO_USE_FUNC))
|
|
status = flSetEnvVolume(variableType,socket,INVALID_VOLUME_NUMBER,value,prevValue);
|
|
break;
|
|
#endif /* not FL_NO_USE_FUNC || VERIFY_WRITE */
|
|
|
|
/* Either global variables , or unknown */
|
|
|
|
default:
|
|
if(socket != INVALID_VOLUME_NUMBER) /* Was not called from flSetEnv */
|
|
{
|
|
DEBUG_PRINT(("Debug: Variable type is either unknown or not socket related.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
status = flSetEnvVolume(variableType,INVALID_VOLUME_NUMBER,INVALID_VOLUME_NUMBER,value,prevValue);
|
|
break;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l S e t E n v All */
|
|
/* */
|
|
/* Change one of TrueFFS environment variables for all systems, sockets */
|
|
/* and partitions. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* variableType : variable type to cahnge */
|
|
/* value : varaible value */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/* prevValue : The previous value of the variable */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus NAMING_CONVENTION flSetEnvAll(FLEnvVars variableType , dword value, dword FAR2 *prevValue)
|
|
{
|
|
FLStatus status = flOK;
|
|
byte socket;
|
|
|
|
switch (variableType) /* Check volume and socket sanity */
|
|
{
|
|
case FL_SET_POLICY: /* Per volume */
|
|
case FL_VERIFY_WRITE_BDTL: /* Per volume */
|
|
case FL_VERIFY_WRITE_BINARY: /* Per volume */
|
|
case FL_VERIFY_WRITE_OTHER: /* Per socket */
|
|
case FL_MTD_BUS_ACCESS_TYPE: /* Per socket */
|
|
for (socket=0;(socket<SOCKETS)&&(status == flOK);socket++)
|
|
status = flSetEnvSocket(variableType,socket,value,prevValue);
|
|
return status;
|
|
default:
|
|
return flSetEnvVolume(variableType,INVALID_VOLUME_NUMBER,INVALID_VOLUME_NUMBER,value,prevValue);
|
|
}
|
|
}
|
|
|
|
#endif /* ENVIRONMENT_VARS */
|
|
|
|
#ifndef FL_NO_USE_FUNC
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l S e t D o c B u s R o u t i n e */
|
|
/* */
|
|
/* Set user defined memory acces routines for DiskOnChip. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* socket : Socket number to install routine for. */
|
|
/* structPtr : Pointer to function structure. */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus NAMING_CONVENTION flSetDocBusRoutine(byte socket, FLAccessStruct FAR1 * structPtr)
|
|
{
|
|
FLFlash* flash;
|
|
|
|
/* Arg sanity check */
|
|
if (socket >= SOCKETS)
|
|
{
|
|
DEBUG_PRINT(("Error : change SOCKETS definition in flcustom.h to support that many sockets.\r\n"));
|
|
return flFeatureNotSupported;
|
|
}
|
|
if(structPtr == NULL)
|
|
{
|
|
DEBUG_PRINT(("ERROR - structPtr argument is NULL.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
|
|
/* Make sure global variables are initialized to their default values */
|
|
flInitGlobalVars();
|
|
|
|
flash = flFlashOf(socket);
|
|
|
|
flash->memWindowSize = structPtr->memWindowSize;
|
|
flash->memRead = structPtr->memRead;
|
|
flash->memWrite = structPtr->memWrite;
|
|
flash->memSet = structPtr->memSet;
|
|
flash->memRead8bit = structPtr->memRead8bit;
|
|
flash->memRead16bit = structPtr->memRead16bit;
|
|
flash->memWrite8bit = structPtr->memWrite8bit;
|
|
flash->memWrite16bit = structPtr->memWrite16bit;
|
|
|
|
flBusConfig[socket] = FL_ACCESS_USER_DEFINED;
|
|
return flOK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l G e t D o c B u s R o u t i n e */
|
|
/* */
|
|
/* Get currently installed memory access routines for DiskOnChip. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* socket : Socket number to install routine for. */
|
|
/* structPtr : Pointer to function structure. */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus NAMING_CONVENTION flGetDocBusRoutine(byte socket, FLAccessStruct FAR1 * structPtr)
|
|
{
|
|
FLFlash* flash;
|
|
|
|
/* Arg sanity check */
|
|
if (socket >= SOCKETS)
|
|
{
|
|
DEBUG_PRINT(("Error : change SOCKETS definition in flcustom.h to support that many sockets.\r\n"));
|
|
return flFeatureNotSupported;
|
|
}
|
|
if(structPtr == NULL)
|
|
{
|
|
DEBUG_PRINT(("ERROR - structPtr argument is NULL.\r\n"));
|
|
return flBadParameter;
|
|
}
|
|
|
|
/* Make sure global variables are initialized to their default values */
|
|
flInitGlobalVars();
|
|
|
|
flash = flFlashOf(socket);
|
|
|
|
structPtr->memWindowSize = flash->memWindowSize;
|
|
structPtr->memRead = flash->memRead;
|
|
structPtr->memWrite = flash->memWrite;
|
|
structPtr->memSet = flash->memSet;
|
|
structPtr->memRead8bit = flash->memRead8bit;
|
|
structPtr->memRead16bit = flash->memRead16bit;
|
|
structPtr->memWrite8bit = flash->memWrite8bit;
|
|
structPtr->memWrite16bit = flash->memWrite16bit;
|
|
structPtr->access = flBusConfig[socket];
|
|
|
|
return flOK;
|
|
}
|
|
|
|
#endif /* FL_NO_USE_FUNC */
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l I n i t G l o b a l V a r s */
|
|
/* */
|
|
/* Initializes the FLite system, environment and access type variables. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* None */
|
|
/* */
|
|
/* Returns: */
|
|
/* None */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void flInitGlobalVars(void)
|
|
{
|
|
int i;
|
|
#ifdef ENVIRONMENT_VARS
|
|
int j;
|
|
#endif /* ENVIRONMENT_VARS */
|
|
|
|
if(initGlobalVarsDone == TRUE)
|
|
return;
|
|
|
|
/* Do not initialize variables on next call */
|
|
initGlobalVarsDone = TRUE;
|
|
|
|
/*
|
|
* Set default values to per socket/volume variables
|
|
*/
|
|
|
|
for(i=0;i<SOCKETS;i++)
|
|
{
|
|
#ifndef FL_NO_USE_FUNC
|
|
flBusConfig[i] = FL_NO_ADDR_SHIFT |
|
|
FL_BUS_HAS_8BIT_ACCESS |
|
|
FL_BUS_HAS_16BIT_ACCESS |
|
|
FL_BUS_HAS_32BIT_ACCESS;
|
|
#endif /* FL_NO_USE_FUNC */
|
|
#ifdef ENVIRONMENT_VARS
|
|
for (j=0;j<MAX_TL_PARTITIONS;j++)
|
|
{
|
|
flPolicy[i][j] = FL_DEFAULT_POLICY; /* FL_COMPLETE_ASAP */
|
|
}
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
|
|
for (j=0;j<MAX_TL_PARTITIONS<<1;j++)
|
|
{
|
|
flVerifyWrite[i][j] = FL_OFF; /* FL_ON , FL_UPS */
|
|
}
|
|
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
|
|
#endif /* ENVIRONMENT_VARS */
|
|
}
|
|
|
|
/*
|
|
* Set default values to per platform variables
|
|
*/
|
|
|
|
#ifdef ENVIRONMENT_VARS
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
|
|
/* Max sectors verified per write operation (must be even number) */
|
|
flSectorsVerifiedPerFolding = 64;
|
|
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
|
|
#ifdef MULTI_DOC
|
|
/* No multi-doc (MTL) */
|
|
flUseMultiDoc = FL_OFF;
|
|
/* MTL defragmentaion mode (0 - standard) */
|
|
flMTLdefragMode = FL_MTL_DEFRAGMENT_ALL_DEVICES;
|
|
#endif /* MULTI_DOC */
|
|
/* Maximum chain length */
|
|
flMaxUnitChain = 20;
|
|
/* Mark the delete sector on the flash */
|
|
flMarkDeleteOnFlash = FL_ON;
|
|
/* Read Only mode */
|
|
flSuspendMode = FL_OFF;
|
|
#endif /* ENVIRONMENT_VARS */
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* m o u n t L o w L e v e l */
|
|
/* */
|
|
/* Mount a volume for low level operations. If a low level routine is */
|
|
/* called and the volume is not mounted for low level operations, this */
|
|
/* routine is called atomatically. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus mountLowLevel(Volume vol)
|
|
{
|
|
checkStatus(flIdentifyFlash(vol.socket,vol.flash));
|
|
vol.flash->setPowerOnCallback(vol.flash);
|
|
vol.flags |= VOLUME_LOW_LVL_MOUNTED;
|
|
|
|
return flOK;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* d i s m o u n t L o w L e v e l */
|
|
/* */
|
|
/* Dismount the volume for low level operations. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static void dismountLowLevel(Volume vol)
|
|
{
|
|
/* mark the volume as unmounted for low level operations.
|
|
And does not change any of the other flags */
|
|
vol.flags &= ~VOLUME_LOW_LVL_MOUNTED;
|
|
}
|
|
|
|
|
|
#ifdef FORMAT_VOLUME
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f i n d F r e e V o l u m e */
|
|
/* */
|
|
/* Search the vols array for an empty cell to hold the new volume . */
|
|
/* */
|
|
/* Parameters: */
|
|
/* socket : Socket number for the new volume. */
|
|
/* partition : Partition number of the new volume. */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, flGeneralFailure if no more */
|
|
/* volumes left. */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus findFreeVolume(byte socket, byte partition)
|
|
{
|
|
byte volNo;
|
|
|
|
for (volNo = noOfSockets;volNo < VOLUMES;volNo++)
|
|
{
|
|
if ((vols[volNo].flags & VOLUME_ACCUPIED) == 0)
|
|
break;
|
|
}
|
|
if (volNo == VOLUMES)
|
|
return flGeneralFailure;
|
|
|
|
handleConversionTable[socket][partition] = volNo;
|
|
vols[volNo].volExecInProgress = &flMutex[socket];
|
|
vols[volNo].socket = vols[socket].socket;
|
|
vols[volNo].flash = vols[socket].flash;
|
|
vols[volNo].tl.socketNo = socket;
|
|
vols[volNo].tl.partitionNo = partition;
|
|
vols[volNo].flags = VOLUME_ACCUPIED;
|
|
return flOK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* d i s m o u n t P h y s i c a l D r i v e */
|
|
/* */
|
|
/* Dismounts all the volumes on a specfic socket, closing all files. */
|
|
/* This call is not normally necessary, unless it is known the volume */
|
|
/* will soon be removed. The routine also clears the volumes entries in */
|
|
/* the volume convertion table, except for partition 0 */
|
|
/* */
|
|
/* Parameters: */
|
|
/* socketNo : Socket number to dismount. */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus dismountPhysicalDrive(byte socketNo)
|
|
{
|
|
byte volNo;
|
|
byte partition;
|
|
|
|
/* Dismount all physical drive volumes */
|
|
|
|
checkStatus(dismountVolume(&vols[socketNo]));
|
|
for(partition = 1;partition < MAX_TL_PARTITIONS; partition++)
|
|
{
|
|
volNo = handleConversionTable[socketNo][partition];
|
|
if (volNo != INVALID_VOLUME_NUMBER)
|
|
{
|
|
checkStatus(dismountVolume(&vols[volNo]));
|
|
handleConversionTable[socketNo][partition]=INVALID_VOLUME_NUMBER;
|
|
vols[volNo].flags = 0;
|
|
}
|
|
}
|
|
return flOK;
|
|
}
|
|
#endif /* FORMAT_VOLUME */
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* d i s m o u n t V o l u m e */
|
|
/* */
|
|
/* Dismounts the volume, closing all files. */
|
|
/* This call is not normally necessary, unless it is known the volume */
|
|
/* will soon be removed. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus dismountVolume(Volume vol)
|
|
{
|
|
if (vol.flags & VOLUME_ABS_MOUNTED)
|
|
{
|
|
FLStatus status = flOK;
|
|
#ifndef FIXED_MEDIA
|
|
status = flMediaCheck(vol.socket);
|
|
#endif
|
|
if (status != flOK)
|
|
vol.flags = 0;
|
|
#if FILES>0
|
|
status = dismountFS(&vol,status);
|
|
#endif
|
|
vol.tl.dismount(vol.tl.rec);
|
|
}
|
|
vol.flags = VOLUME_ACCUPIED; /* mark volume unmounted */
|
|
|
|
return flOK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* s e t B u s y */
|
|
/* */
|
|
/* Notifies the start and end of a file-system operation. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* state : FL_ON (1) = operation entry */
|
|
/* FL_OFF(0) = operation exit */
|
|
/* partition : Partition number of the drive */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus setBusy(Volume vol, FLBoolean state, byte partition)
|
|
{
|
|
FLStatus status = flOK;
|
|
|
|
if (state == FL_ON) {
|
|
|
|
if (!flTakeMutex(execInProgress))
|
|
return flDriveNotAvailable;
|
|
|
|
/* Mark current partition for MTD verify write */
|
|
vol.socket->curPartition = partition;
|
|
flSocketSetBusy(vol.socket,FL_ON);
|
|
flNeedVcc(vol.socket);
|
|
if (vol.flags & VOLUME_ABS_MOUNTED)
|
|
status = vol.tl.tlSetBusy(vol.tl.rec,FL_ON);
|
|
}
|
|
else {
|
|
if (vol.flags & VOLUME_ABS_MOUNTED)
|
|
status = vol.tl.tlSetBusy(vol.tl.rec,FL_OFF);
|
|
|
|
flDontNeedVcc(vol.socket);
|
|
flSocketSetBusy(vol.socket,FL_OFF);
|
|
flFreeMutex(execInProgress);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f i n d S e c t o r */
|
|
/* */
|
|
/* Locates a sector in the buffer or maps it */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* sectorNo : Sector no. to locate */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
const void FAR0 *findSector(Volume vol, SectorNo sectorNo)
|
|
{
|
|
return
|
|
#if FILES > 0
|
|
(sectorNo == vol.volBuffer.sectorNo && &vol == vol.volBuffer.owner) ?
|
|
vol.volBuffer.flData :
|
|
#endif
|
|
vol.tl.mapSector(vol.tl.rec,sectorNo,NULL);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* a b s M o u n t V o l u m e */
|
|
/* */
|
|
/* Mounts the Flash volume and assume that volume has no FAT */
|
|
/* */
|
|
/* In case the inserted volume has changed, or on the first access to */
|
|
/* the file system, it should be mounted before file operations can be */
|
|
/* done on it. */
|
|
/* Mounting a volume has the effect of discarding all open files (the */
|
|
/* files cannot be properly closed since the original volume is gone), */
|
|
/* and turning off the media-change indication to allow file processing */
|
|
/* calls. */
|
|
/* */
|
|
/* The volume automatically becomes unmounted if it is removed or */
|
|
/* changed. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus absMountVolume(Volume vol)
|
|
{
|
|
unsigned volNo = (unsigned)(&vol - vols);
|
|
#ifdef WRITE_PROTECTION
|
|
PartitionTable FAR0 *partitionTable;
|
|
#endif
|
|
|
|
checkStatus(dismountVolume(&vol));
|
|
|
|
/* Try to mount translation layer */
|
|
|
|
checkStatus(flMount(volNo,vol.tl.socketNo,&vol.tl,TRUE,vol.flash));
|
|
|
|
vol.bootSectorNo = 0; /* assume sector 0 is DOS boot block */
|
|
#ifdef WRITE_PROTECTION
|
|
partitionTable = (PartitionTable FAR0 *) findSector(&vol,0);
|
|
if((partitionTable == NULL)||
|
|
(partitionTable==dataErrorToken)||
|
|
(LE2(partitionTable->signature) != PARTITION_SIGNATURE))
|
|
vol.password[0] = vol.password[1] = 0;
|
|
else
|
|
{
|
|
vol.password[0] = vol.password[1] = 0;
|
|
if (UNAL4(partitionTable->passwordInfo[0]) == 0 &&
|
|
(UNAL4(partitionTable->passwordInfo[1]) != 0 ||
|
|
UNAL4(partitionTable->passwordInfo[2]) != 0)) {
|
|
vol.password[0] = UNAL4(partitionTable->passwordInfo[1]);
|
|
vol.password[1] = UNAL4(partitionTable->passwordInfo[2]);
|
|
vol.flags |= VOLUME_WRITE_PROTECTED;
|
|
}
|
|
}
|
|
#endif /* WRITE_PROTECTION */
|
|
/* Disable FAT monitoring */
|
|
vol.firstFATSectorNo = vol.secondFATSectorNo = 0;
|
|
vol.flags |= VOLUME_ABS_MOUNTED; /* Enough to do abs operations */
|
|
|
|
return flOK;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* m o u n t V o l u m e */
|
|
/* */
|
|
/* Mounts the Flash volume. */
|
|
/* */
|
|
/* In case the inserted volume has changed, or on the first access to */
|
|
/* the file system, it should be mounted before file operations can be */
|
|
/* done on it. */
|
|
/* Mounting a volume has the effect of discarding all open files (the */
|
|
/* files cannot be properly closed since the original volume is gone), */
|
|
/* and turning off the media-change indication to allow file processing */
|
|
/* calls. */
|
|
/* */
|
|
/* The volume automatically becomes unmounted if it is removed or */
|
|
/* changed. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/* bootSectors : Returns the number of sectors, flMountVolume */
|
|
/* skipps. */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus mountVolume(Volume vol,unsigned FAR2* bootSectors)
|
|
{
|
|
SectorNo noOfSectors;
|
|
PartitionTable FAR0 *partitionTable;
|
|
Partition ptEntry;
|
|
DOSBootSector FAR0 *bootSector;
|
|
unsigned ptCount,extended_depth,ptSector;
|
|
FLBoolean primaryPtFound = FALSE, extendedPtFound = TRUE;
|
|
|
|
*bootSectors=0;
|
|
checkStatus(absMountVolume(&vol));
|
|
|
|
for(extended_depth = 0,ptSector = 0;
|
|
(extended_depth<MAX_PARTITION_DEPTH) &&
|
|
(primaryPtFound==FALSE) &&
|
|
(extendedPtFound==TRUE);
|
|
extended_depth++) {
|
|
|
|
extendedPtFound=FALSE;
|
|
/* Read in paritition table */
|
|
|
|
partitionTable = (PartitionTable FAR0 *) findSector(&vol,ptSector);
|
|
|
|
if(partitionTable == NULL) {
|
|
vol.tl.dismount(vol.tl.rec);
|
|
return flSectorNotFound;
|
|
}
|
|
if(partitionTable==dataErrorToken) {
|
|
vol.tl.dismount(vol.tl.rec);
|
|
return flDataError;
|
|
}
|
|
|
|
if (LE2(partitionTable->signature) != PARTITION_SIGNATURE)
|
|
break;
|
|
for(ptCount=0;
|
|
(ptCount<4) && (primaryPtFound==FALSE) && (extendedPtFound==FALSE);
|
|
ptCount++) {
|
|
|
|
ptEntry = partitionTable->ptEntry[ptCount];
|
|
|
|
switch (ptEntry.type) {
|
|
case FAT12_PARTIT:
|
|
case FAT16_PARTIT:
|
|
case DOS4_PARTIT:
|
|
primaryPtFound = TRUE;
|
|
vol.bootSectorNo =
|
|
(unsigned) UNAL4(ptEntry.startingSectorOfPartition);
|
|
*bootSectors=vol.bootSectorNo;
|
|
break;
|
|
case EX_PARTIT:
|
|
extendedPtFound = TRUE;
|
|
ptSector = (unsigned)UNAL4(ptEntry.startingSectorOfPartition);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bootSector = (DOSBootSector FAR0 *) findSector(&vol,vol.bootSectorNo);
|
|
if(bootSector == NULL)
|
|
return flSectorNotFound;
|
|
|
|
if(bootSector==dataErrorToken)
|
|
return flDataError;
|
|
|
|
/* Do the customary sanity checks */
|
|
if (!(bootSector->bpb.jumpInstruction[0] == 0xe9 ||
|
|
(bootSector->bpb.jumpInstruction[0] == 0xeb &&
|
|
bootSector->bpb.jumpInstruction[2] == 0x90))) {
|
|
DEBUG_PRINT(("Debug: did not recognize format.\r\n"));
|
|
return flNonFATformat;
|
|
}
|
|
|
|
/* See if we handle this sector size */
|
|
if (UNAL2(bootSector->bpb.bytesPerSector) != SECTOR_SIZE)
|
|
return flFormatNotSupported;
|
|
|
|
vol.sectorsPerCluster = bootSector->bpb.sectorsPerCluster;
|
|
vol.numberOfFATS = bootSector->bpb.noOfFATS;
|
|
vol.sectorsPerFAT = LE2(bootSector->bpb.sectorsPerFAT);
|
|
vol.firstFATSectorNo = vol.bootSectorNo +
|
|
LE2(bootSector->bpb.reservedSectors);
|
|
vol.secondFATSectorNo = vol.firstFATSectorNo +
|
|
LE2(bootSector->bpb.sectorsPerFAT);
|
|
vol.rootDirectorySectorNo = vol.firstFATSectorNo +
|
|
bootSector->bpb.noOfFATS * LE2(bootSector->bpb.sectorsPerFAT);
|
|
vol.sectorsInRootDirectory =
|
|
(UNAL2(bootSector->bpb.rootDirectoryEntries) * DIRECTORY_ENTRY_SIZE - 1) /
|
|
SECTOR_SIZE + 1;
|
|
vol.firstDataSectorNo = vol.rootDirectorySectorNo +
|
|
vol.sectorsInRootDirectory;
|
|
|
|
noOfSectors = UNAL2(bootSector->bpb.totalSectorsInVolumeDOS3);
|
|
if (noOfSectors == 0)
|
|
noOfSectors = (SectorNo) LE4(bootSector->bpb.totalSectorsInVolume);
|
|
|
|
|
|
vol.maxCluster = (unsigned) ((noOfSectors + vol.bootSectorNo - vol.firstDataSectorNo) /
|
|
vol.sectorsPerCluster) + 1;
|
|
|
|
if (vol.maxCluster < 4085) {
|
|
#ifdef FAT_12BIT
|
|
vol.flags |= VOLUME_12BIT_FAT; /* 12-bit FAT */
|
|
#else
|
|
DEBUG_PRINT(("Debug: FAT_12BIT must be defined.\r\n"));
|
|
return flFormatNotSupported;
|
|
#endif
|
|
}
|
|
vol.bytesPerCluster = vol.sectorsPerCluster * SECTOR_SIZE;
|
|
vol.allocationRover = 2; /* Set rover at first cluster */
|
|
vol.flags |= VOLUME_MOUNTED; /* That's it */
|
|
return flOK;
|
|
}
|
|
|
|
#ifndef FL_READ_ONLY
|
|
#ifdef DEFRAGMENT_VOLUME
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* d e f r a g m e n t V o l u m e */
|
|
/* */
|
|
/* Performs a general defragmentation and recycling of non-writable */
|
|
/* Flash areas, to achieve optimal write speed. */
|
|
/* */
|
|
/* NOTE: The required number of sectors (in irLength) may be changed */
|
|
/* (from another execution thread) while defragmentation is active. In */
|
|
/* particular, the defragmentation may be cut short after it began by */
|
|
/* modifying the irLength field to 0. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* ioreq->irLength : Minimum number of sectors to make available */
|
|
/* for writes. */
|
|
/* */
|
|
/* Returns: */
|
|
/* ioreq->irLength : Actual number of sectors available for writes */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus defragmentVolume(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
return vol.tl.defragment(vol.tl.rec,&ioreq->irLength);
|
|
}
|
|
|
|
#endif /* DEFRAGMENT_VOLUME */
|
|
|
|
#ifdef FORMAT_VOLUME
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* f l F o r m a t V o l u m e */
|
|
/* */
|
|
/* Formats a volume, writing a new and empty file-system. All existing */
|
|
/* data is destroyed. Optionally, a low-level FTL formatting is also */
|
|
/* done. */
|
|
/* Formatting leaves the volume in the dismounted state, so that a */
|
|
/* flMountVolume call is necessary after it. */
|
|
/* */
|
|
/* Note: This routine was left for backwards compatibility with OSAK 4.2 */
|
|
/* and down therfore it is strongly recommended to use the */
|
|
/* flFormatPhysicalDrive routine instead. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irHandle : Drive number (0, 1, ...) */
|
|
/* irFlags : FAT_ONLY_FORMAT : Do FAT formatting only */
|
|
/* TL_FORMAT_ONLY : Do TL format only */
|
|
/* TL_FORMAT : Translation layer + FAT */
|
|
/* TL_FORMAT_IF_NEEDED: Do TL formatting only if */
|
|
/* current format is invalid */
|
|
/* but perform FAT anyway */
|
|
/* irData : Address of FormatParams structure to use */
|
|
/* (defined in flformat.h) */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
static FLStatus bdFormatVolume(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
FormatParams FAR2 *userFp = (FormatParams FAR2 *) ioreq->irData;
|
|
BDTLPartitionFormatParams bdtlFp;
|
|
TLFormatParams tlFp;
|
|
FLBoolean mountOK = FALSE;
|
|
FLStatus status;
|
|
byte socket = FL_GET_SOCKET_FROM_HANDLE(ioreq);
|
|
|
|
/* Convert argument to TLFormatParmas */
|
|
|
|
tlFp.noOfBinaryPartitions = 0;
|
|
tlFp.noOfBDTLPartitions = 1;
|
|
tlFp.BDTLPartitionInfo = NULL;
|
|
tlFp.binaryPartitionInfo = NULL;
|
|
tlFp.bootImageLen = userFp->bootImageLen;
|
|
tlFp.percentUse = (byte)userFp->percentUse;
|
|
tlFp.noOfSpareUnits = (byte)userFp->noOfSpareUnits;
|
|
tlFp.noOfCascadedDevices = 0;
|
|
tlFp.progressCallback = userFp->progressCallback;
|
|
tlFp.vmAddressingLimit = userFp->vmAddressingLimit;
|
|
tlFp.embeddedCISlength = (word)userFp->embeddedCISlength;
|
|
tlFp.embeddedCIS = (byte FAR1 *)userFp->embeddedCIS;
|
|
tlFp.flags = FL_LEAVE_BINARY_AREA;
|
|
#ifdef WRITE_EXB_IMAGE
|
|
tlFp.exbLen = 0;
|
|
#endif /* WRITE_EXB_IMAGE */
|
|
#ifdef HW_PROTECTION
|
|
/* protectionKey[8]; */
|
|
tlFp.protectionType = 0;
|
|
#endif /* HW_PROTECTION */
|
|
|
|
/* Dismount all physical drive volumes and set handle to the first */
|
|
|
|
checkStatus(dismountPhysicalDrive(socket));
|
|
pVol = &vols[socket];
|
|
|
|
/* Format according to the irFlags argument */
|
|
|
|
if ((ioreq->irFlags & TL_FORMAT)||(ioreq->irFlags & TL_FORMAT_ONLY))
|
|
{
|
|
checkStatus(flFormat(socket,&tlFp,vol.flash));
|
|
}
|
|
else
|
|
{
|
|
status = flMount(socket,socket,&vol.tl,FALSE,vol.flash); /* Try to mount translation layer */
|
|
mountOK = TRUE;
|
|
if ((status == flUnknownMedia || status == flBadFormat) &&
|
|
(ioreq->irFlags & TL_FORMAT_IF_NEEDED))
|
|
{
|
|
status = flFormat(socket,&tlFp,vol.flash);
|
|
mountOK = FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* assume sector 0 is DOS boot block */
|
|
vol.bootSectorNo = 0;
|
|
/* Disable FAT monitoring */
|
|
vol.firstFATSectorNo = vol.secondFATSectorNo = 0;
|
|
/* Enough to do abs operations */
|
|
vol.flags |= VOLUME_ABS_MOUNTED;
|
|
}
|
|
if (status != flOK)
|
|
return status;
|
|
}
|
|
|
|
if (!mountOK)
|
|
checkStatus(absMountVolume(&vol)); /* Mount the first partition */
|
|
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
|
|
if(vol.tl.checkVolume != NULL)
|
|
checkStatus(vol.tl.checkVolume(vol.tl.rec));
|
|
#endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
|
|
|
|
if(!(ioreq->irFlags & TL_FORMAT_ONLY))
|
|
{
|
|
/* build BDTL record for dos format routine */
|
|
|
|
tffscpy(bdtlFp.volumeId,userFp->volumeId,4);
|
|
bdtlFp.volumeLabel = (byte FAR1 *)userFp->volumeLabel;
|
|
bdtlFp.noOfFATcopies = (byte)userFp->noOfFATcopies;
|
|
bdtlFp.flags = TL_FORMAT_FAT;
|
|
checkStatus(flDosFormat(&vol.tl,&bdtlFp));
|
|
}
|
|
return flOK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l F o r m a t P h y s i c a l D r i v e */
|
|
/* */
|
|
/* Low Level formats the media while partitioning it. */
|
|
/* optionaly the followng additional formats are placed */
|
|
/* 1) writing a new and empty file-system */
|
|
/* 2) Compressed media format */
|
|
/* 3) Quick Mount format */
|
|
/* */
|
|
/* 4) Place M-systems EXB file on the media */
|
|
/* All existing data is destroyed. */
|
|
/* Formatting leaves the volume in the dismounted state, so that a */
|
|
/* flMountVolume call is necessary after it. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irHandle : Drive number (0, 1, ...) */
|
|
/* irFlags : */
|
|
/* TL_NORMAL_FORMAT : Normal format */
|
|
/* TL_LEAVE_BINARY_AREA : Leave binary area unchanged */
|
|
/* */
|
|
/* irData : Address of FormatParams2 structure to use */
|
|
/* (defined in flformat.h) */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus bdFormatPhysicalDrive(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
FormatParams2 FAR2* userFp = (FormatParams2 FAR2 *) ioreq->irData;
|
|
BDTLPartitionFormatParams FAR2* bdtl;
|
|
TLFormatParams tlFp;
|
|
byte socket = FL_GET_SOCKET_FROM_HANDLE(ioreq);
|
|
byte partition;
|
|
byte volNo;
|
|
#ifdef COMPRESSION
|
|
FLStatus status;
|
|
#endif /* COMPRESSION */
|
|
|
|
/***********************************************/
|
|
/* Convert format parameters to TLFormatParams */
|
|
/***********************************************/
|
|
|
|
if (userFp->BDTLPartitionInfo == NULL)
|
|
return flBadParameter;
|
|
|
|
/* Note that the the BDTL partition are shiftet so that the second
|
|
becomes the first ... . This is for backwards compatibility with
|
|
FTP \ NFTL where the first partition is not given as an array */
|
|
|
|
tlFp.bootImageLen = -1; /* either all or nothing */
|
|
tlFp.percentUse = userFp->percentUse;
|
|
tlFp.noOfBDTLPartitions = userFp->noOfBDTLPartitions;
|
|
tlFp.noOfBinaryPartitions = userFp->noOfBinaryPartitions;
|
|
tlFp.BDTLPartitionInfo = userFp->BDTLPartitionInfo;
|
|
tlFp.binaryPartitionInfo = userFp->binaryPartitionInfo;
|
|
tlFp.progressCallback = userFp->progressCallback;
|
|
tlFp.vmAddressingLimit = userFp->vmAddressingLimit;
|
|
tlFp.embeddedCISlength = userFp->embeddedCISlength;
|
|
tlFp.embeddedCIS = userFp->embeddedCIS;
|
|
tlFp.cascadedDeviceNo = userFp->cascadedDeviceNo;
|
|
tlFp.noOfCascadedDevices = userFp->noOfCascadedDevices;
|
|
tlFp.flags = (byte)ioreq->irFlags;
|
|
|
|
/* Convert last partition arguments from array to dedicated fields */
|
|
|
|
bdtl = userFp->BDTLPartitionInfo;
|
|
bdtl += (userFp->noOfBDTLPartitions - 1);
|
|
tffscpy(tlFp.volumeId,bdtl->volumeId,4);
|
|
tlFp.noOfSpareUnits = (byte)bdtl->noOfSpareUnits;
|
|
tlFp.volumeLabel = bdtl->volumeLabel;
|
|
tlFp.noOfFATcopies = bdtl->noOfFATcopies;
|
|
#ifdef HW_PROTECTION
|
|
tffscpy(tlFp.protectionKey,bdtl->protectionKey,PROTECTION_KEY_LENGTH);
|
|
tlFp.protectionType = bdtl->protectionType;
|
|
#endif /* HW_PROTECTION */
|
|
|
|
/* Dismount all physical drive volumes */
|
|
|
|
checkStatus(dismountPhysicalDrive(socket));
|
|
|
|
/**********************/
|
|
/* Analize EXB buffer */
|
|
/**********************/
|
|
|
|
pVol = &vols[socket];
|
|
#ifdef WRITE_EXB_IMAGE
|
|
if ((ioreq->irFlags & TL_LEAVE_BINARY_AREA) ||
|
|
((userFp->exbBufferLen <= 0) && (userFp->exbLen == 0)))
|
|
{
|
|
tlFp.exbLen = 0;
|
|
}
|
|
else
|
|
{
|
|
if (userFp->exbLen <= 0)
|
|
{
|
|
checkStatus(getExbInfo(&vol, userFp->exbBuffer,
|
|
userFp->exbBufferLen,
|
|
userFp->exbFlags));
|
|
tlFp.exbLen = vol.binaryLength;
|
|
}
|
|
else
|
|
{
|
|
tlFp.exbLen = userFp->exbLen;
|
|
}
|
|
}
|
|
#endif /* WRITE_EXB_IMAGE */
|
|
|
|
/*************************************************/
|
|
/* Perform low level format and write EXB buffer */
|
|
/*************************************************/
|
|
|
|
checkStatus(flFormat(socket,&tlFp,vol.flash));
|
|
|
|
/****************************************/
|
|
/* perform FAT and ZIP format if needed */
|
|
/****************************************/
|
|
|
|
for(partition=0, bdtl = userFp->BDTLPartitionInfo;
|
|
partition<userFp->noOfBDTLPartitions;
|
|
partition++,bdtl++)
|
|
{
|
|
if ( partition > 0)
|
|
checkStatus(findFreeVolume(socket,partition));
|
|
volNo = handleConversionTable[socket][partition];
|
|
pVol = &vols[volNo];
|
|
#ifdef COMPRESSION
|
|
if(bdtl->flags & TL_FORMAT_COMPRESSED)
|
|
{
|
|
checkStatus(flMount(volNo,socket,&(vol.tl),FALSE,vol.flash));
|
|
status = flFormatZIP(volNo,&vol.tl);
|
|
vol.tl.dismount(vol.tl.rec);
|
|
if(status!=flOK)
|
|
return status;
|
|
}
|
|
#endif /* COMPRESSION */
|
|
|
|
checkStatus(absMountVolume(&vol));
|
|
#if (defined(VERIFY_WRITE) || defined(VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
|
|
if(vol.tl.checkVolume != NULL)
|
|
checkStatus(vol.tl.checkVolume(vol.tl.rec));
|
|
#endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
|
|
if(bdtl->flags & TL_FORMAT_FAT) /* perform FAT format as well */
|
|
checkStatus(flDosFormat(&vol.tl,bdtl));
|
|
checkStatus(dismountVolume(&vol));
|
|
}
|
|
|
|
#ifdef WRITE_EXB_IMAGE
|
|
if (userFp->exbBufferLen > 0 )
|
|
{
|
|
pVol = &vols[socket];
|
|
checkStatus(placeExbByBuffer(&vol,(byte FAR1 *)userFp->exbBuffer,
|
|
userFp->exbBufferLen,userFp->exbWindow,userFp->exbFlags));
|
|
}
|
|
#endif /* WRITE_EXB_IMAGE */
|
|
|
|
checkStatus(mountLowLevel(&vol));
|
|
if (vol.flash->download!=NULL)
|
|
{
|
|
return vol.flash->download(vol.flash); /* download IPL */
|
|
}
|
|
return flOK;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* f l F o r m a t L o g i c a l D r i v e */
|
|
/* */
|
|
/* Formats a logical drive, optionaly writing a new and empty */
|
|
/* file-system and or a compressed format. All existing */
|
|
/* data is destroyed. */
|
|
/* Formatting leaves the volume in the dismounted state, so that a */
|
|
/* flMountVolume call is necessary after it. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irHandle : Drive number (0, 1, ...) */
|
|
/* irData : Address of BDTLPartitionFormatParams to use */
|
|
/* (defined in flformat.h) */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
static FLStatus bdFormatLogicalDrive(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
BDTLPartitionFormatParams FAR2 *userFp =
|
|
(BDTLPartitionFormatParams FAR2 *) ioreq->irData;
|
|
byte volNo = (byte)(&vol-vols);
|
|
#ifdef COMPRESSION
|
|
FLStatus status;
|
|
#endif /* COMPRESSION */
|
|
|
|
checkStatus(flMount(volNo,vol.tl.socketNo,&(vol.tl),FALSE,vol.flash));
|
|
/* assume sector 0 is DOS boot block */
|
|
vol.bootSectorNo = 0;
|
|
/* Disable FAT monitoring */
|
|
vol.firstFATSectorNo = vol.secondFATSectorNo = 0;
|
|
/* Enough to do abs operations */
|
|
vol.flags |= VOLUME_ABS_MOUNTED;
|
|
|
|
#ifdef COMPRESSION
|
|
if(userFp->flags & TL_FORMAT_COMPRESSED)
|
|
{
|
|
status = flFormatZIP(volNo,&vol.tl,vol.flash);
|
|
vol.tl.dismount(vol.tl.rec);
|
|
if(status!=flOK)
|
|
return status;
|
|
}
|
|
#endif /* COMPRESSION */
|
|
|
|
if(userFp->flags & TL_FORMAT_FAT) /* perform FAT format as well */
|
|
{
|
|
checkStatus(absMountVolume(&vol));
|
|
checkStatus(flDosFormat(&vol.tl,userFp));
|
|
checkStatus(dismountVolume(&vol));
|
|
}
|
|
return flOK;
|
|
}
|
|
#endif /* FORMAT_VOLUME */
|
|
|
|
#endif /* FL_READ_ONLY */
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* s e c t o r s I n V o l u m e */
|
|
/* */
|
|
/* Defines actual number of virtual sectors according to the low-level */
|
|
/* format of the media. */
|
|
/* */
|
|
/* Returns: */
|
|
/* vol : Pointer identifying drive */
|
|
/* ioreq->irLength : Actual number of virtual sectors in volume */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
static FLStatus sectorsInVolume(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
dword sectorsInVol = vol.tl.sectorsInVolume(vol.tl.rec);
|
|
if(sectorsInVol<=vol.bootSectorNo) {
|
|
ioreq->irLength = 0;
|
|
return flGeneralFailure;
|
|
}
|
|
|
|
ioreq->irLength = sectorsInVol-vol.bootSectorNo;
|
|
return flOK;
|
|
}
|
|
|
|
|
|
#ifdef ABS_READ_WRITE
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* a b s R e a d */
|
|
/* */
|
|
/* Reads absolute sectors by sector no. */
|
|
/* */
|
|
/* Note that if readSecots is not implemented irSectoCount will not */
|
|
/* return the actual number of sectors written in case the operation */
|
|
/* failed in the middle. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irHandle : Drive number (0, 1, ...) */
|
|
/* irData : Address of user buffer to read into */
|
|
/* irSectorNo : First sector no. to read (sector 0 is the */
|
|
/* DOS boot sector). */
|
|
/* irSectorCount : Number of consectutive sectors to read */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/* irSectorCount : Number of sectors actually read */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus absRead(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
char FAR1 *userBuffer = (char FAR1 *) ioreq->irData;
|
|
SectorNo currSector = vol.bootSectorNo + ioreq->irSectorNo;
|
|
void FAR0 *mappedSector;
|
|
FLStatus status;
|
|
|
|
if (vol.tl.readSectors != NULL)
|
|
{
|
|
status = vol.tl.readSectors(vol.tl.rec , currSector,
|
|
(byte FAR1* )ioreq->irData , ioreq->irSectorCount);
|
|
|
|
if (status == flSectorNotFound)
|
|
{
|
|
/* Do not report unassigned sectors. Simply report all 0's */
|
|
if(vol.tl.sectorsInVolume(vol.tl.rec) >=
|
|
(currSector+ioreq->irSectorCount))
|
|
return flOK;
|
|
}
|
|
return status;
|
|
}
|
|
else
|
|
{
|
|
SectorNo sectorCount = (SectorNo)ioreq->irSectorCount;
|
|
for (ioreq->irSectorCount = 0;
|
|
(SectorNo)(ioreq->irSectorCount) < sectorCount;
|
|
ioreq->irSectorCount++, currSector++, userBuffer += SECTOR_SIZE)
|
|
{
|
|
#ifdef SCATTER_GATHER
|
|
userBuffer = *((char FAR1 **)(ioreq->irData) +
|
|
(int)(ioreq->irSectorCount));
|
|
#endif
|
|
mappedSector = (void FAR0 *)findSector(&vol,currSector);
|
|
if (mappedSector)
|
|
{
|
|
if(mappedSector==dataErrorToken)
|
|
return flDataError;
|
|
|
|
tffscpy(userBuffer,mappedSector,SECTOR_SIZE);
|
|
}
|
|
else
|
|
{
|
|
if(vol.tl.sectorsInVolume(vol.tl.rec)<=(currSector))
|
|
return flSectorNotFound;
|
|
tffsset(userBuffer,0,SECTOR_SIZE);
|
|
}
|
|
}
|
|
}
|
|
return flOK;
|
|
}
|
|
|
|
|
|
#ifndef FL_READ_ONLY
|
|
/*----------------------------------------------------------------------*/
|
|
/* r e p l a c e F A T s e c t o r */
|
|
/* */
|
|
/* Monitors sector deletions in the FAT. */
|
|
/* */
|
|
/* When a FAT block is about to be written by an absolute write, this */
|
|
/* routine will first scan whether any sectors are being logically */
|
|
/* deleted by this FAT update, and if so, it will delete-sector them */
|
|
/* before the actual FAT update takes place. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* sectorNo : FAT Sector no. about to be written */
|
|
/* newFATsector : Address of FAT sector about to be written */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus replaceFATsector(Volume vol,
|
|
SectorNo sectorNo,
|
|
const char FAR1 *newFATsector)
|
|
{
|
|
const char FAR0 *oldFATsector = (const char FAR0 *)findSector(&vol,sectorNo);
|
|
SectorNo firstSector;
|
|
unsigned firstCluster;
|
|
#ifdef FAT_12BIT
|
|
word FAThalfBytes;
|
|
word halfByteOffset;
|
|
#else
|
|
word byteOffset;
|
|
#endif
|
|
|
|
if((oldFATsector==NULL) || oldFATsector==dataErrorToken)
|
|
return flOK;
|
|
|
|
#ifdef FAT_12BIT
|
|
FAThalfBytes = vol.flags & VOLUME_12BIT_FAT ? 3 : 4;
|
|
|
|
firstCluster = (FAThalfBytes == 3) ?
|
|
(((unsigned) (sectorNo - vol.firstFATSectorNo) * (2 * SECTOR_SIZE) + 2) / 3) :
|
|
((unsigned) (sectorNo - vol.firstFATSectorNo) * (SECTOR_SIZE>>1));
|
|
firstSector = ((SectorNo) firstCluster - 2) *
|
|
vol.sectorsPerCluster + vol.firstDataSectorNo;
|
|
halfByteOffset = (firstCluster * FAThalfBytes) & ((SECTOR_SIZE<<1) - 1);
|
|
|
|
/* Find if any clusters were logically deleted, and if so, delete them */
|
|
/* NOTE: We are skipping over 12-bit FAT entries which span more than */
|
|
/* one sector. Nobody's perfect anyway. */
|
|
for (; halfByteOffset < ((SECTOR_SIZE<<1) - 2);
|
|
firstSector += vol.sectorsPerCluster,
|
|
halfByteOffset += FAThalfBytes)
|
|
{
|
|
unsigned short oldFATentry, newFATentry;
|
|
|
|
#ifdef FL_BIG_ENDIAN
|
|
oldFATentry = LE2(*(LEushort FAR0 *)(oldFATsector + (halfByteOffset>>1)));
|
|
newFATentry = LE2(*(LEushort FAR1 *)(newFATsector + (halfByteOffset>>1)));
|
|
#else
|
|
oldFATentry = UNAL2(*(Unaligned FAR0 *)(oldFATsector + (halfByteOffset / 2)));
|
|
newFATentry = UNAL2(*(Unaligned FAR1 *)(newFATsector + (halfByteOffset / 2)));
|
|
#endif
|
|
if (halfByteOffset & 1) {
|
|
oldFATentry >>= 4;
|
|
newFATentry >>= 4;
|
|
}
|
|
else if (FAThalfBytes == 3) {
|
|
oldFATentry &= 0xfff;
|
|
newFATentry &= 0xfff;
|
|
}
|
|
#else
|
|
firstCluster = ((unsigned) (sectorNo - vol.firstFATSectorNo) << (SECTOR_SIZE_BITS-1));
|
|
firstSector = ((SectorNo) firstCluster - 2) * vol.sectorsPerCluster +
|
|
vol.firstDataSectorNo;
|
|
|
|
/* Find if any clusters were logically deleted, and if so, delete them */
|
|
for (byteOffset = 0; byteOffset < SECTOR_SIZE;
|
|
firstSector += vol.sectorsPerCluster, byteOffset += 2) {
|
|
unsigned short oldFATentry = LE2(*(LEushort FAR0 *)(oldFATsector + byteOffset));
|
|
unsigned short newFATentry = LE2(*(LEushort FAR1 *)(newFATsector + byteOffset));
|
|
#endif
|
|
|
|
if (oldFATentry != FAT_FREE && newFATentry == FAT_FREE)
|
|
checkStatus(vol.tl.deleteSector(vol.tl.rec,firstSector,vol.sectorsPerCluster));
|
|
|
|
/* make sure sector is still there */
|
|
oldFATsector = (const char FAR0 *) findSector(&vol,sectorNo);
|
|
}
|
|
|
|
return flOK;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* a b s W r i t e */
|
|
/* */
|
|
/* Writes absolute sectors by sector no. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irHandle : Drive number (0, 1, ...) */
|
|
/* irData : Address of user buffer to write from */
|
|
/* irSectorNo : First sector no. to write (sector 0 is the */
|
|
/* DOS boot sector). */
|
|
/* irSectorCount : Number of consectutive sectors to write */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/* irSectorCount : Number of sectors actually written */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus absWrite(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
char FAR1 *userBuffer = (char FAR1 *) ioreq->irData;
|
|
SectorNo currSector = vol.bootSectorNo + ioreq->irSectorNo;
|
|
SectorNo sectorCount = (SectorNo)ioreq->irSectorCount;
|
|
|
|
if (currSector < vol.secondFATSectorNo &&
|
|
currSector + sectorCount > vol.firstFATSectorNo) {
|
|
SectorNo iSector;
|
|
|
|
for (iSector = 0; iSector < sectorCount;
|
|
iSector++, currSector++, userBuffer += SECTOR_SIZE) {
|
|
|
|
if (currSector >= vol.firstFATSectorNo &&
|
|
currSector < vol.secondFATSectorNo)
|
|
replaceFATsector(&vol,currSector,userBuffer);
|
|
}
|
|
|
|
userBuffer = (char FAR1 *) ioreq->irData;
|
|
currSector = (SectorNo)vol.bootSectorNo + (SectorNo)ioreq->irSectorNo;
|
|
}
|
|
if (vol.tl.writeMultiSector != NULL)
|
|
{
|
|
checkStatus(vol.tl.writeMultiSector(vol.tl.rec, currSector,
|
|
ioreq->irData,ioreq->irSectorCount));
|
|
}
|
|
else
|
|
{
|
|
for (ioreq->irSectorCount = 0;
|
|
(SectorNo)(ioreq->irSectorCount) < sectorCount;
|
|
ioreq->irSectorCount++, currSector++, userBuffer += SECTOR_SIZE)
|
|
{
|
|
#if FILES>0
|
|
if ((currSector == vol.volBuffer.sectorNo) &&
|
|
(&vol == vol.volBuffer.owner))
|
|
{
|
|
vol.volBuffer.sectorNo = UNASSIGNED_SECTOR; /* no longer valid */
|
|
vol.volBuffer.dirty = vol.volBuffer.checkPoint = FALSE;
|
|
}
|
|
#endif
|
|
|
|
#ifdef SCATTER_GATHER
|
|
userBuffer = *((char FAR1 **)(ioreq->irData)+(int)(ioreq->irSectorCount));
|
|
#endif
|
|
checkStatus(vol.tl.writeSector(vol.tl.rec,currSector,userBuffer));
|
|
}
|
|
}
|
|
return flOK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* a b s D e l e t e */
|
|
/* */
|
|
/* Marks absolute sectors by sector no. as deleted. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irHandle : Drive number (0, 1, ...) */
|
|
/* irSectorNo : First sector no. to write (sector 0 is the */
|
|
/* DOS boot sector). */
|
|
/* irSectorCount : Number of consectutive sectors to delete */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus absDelete(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
SectorNo first;
|
|
first = (SectorNo)(vol.bootSectorNo + ioreq->irSectorNo);
|
|
return vol.tl.deleteSector(vol.tl.rec,first,(SectorNo)ioreq->irSectorCount);
|
|
}
|
|
|
|
#endif /* FL_READ_ONLY */
|
|
|
|
#ifndef NO_PHYSICAL_IO
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l A b s A d d r e s s */
|
|
/* */
|
|
/* Returns the current physical media offset of an absolute sector by */
|
|
/* sector no. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irHandle : Drive number (0, 1, ...) */
|
|
/* irSectorNo : Sector no. to address (sector 0 is the DOS */
|
|
/* boot sector) */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/* irCount : Offset of the sector on the physical media */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus absAddress(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
CardAddress cardOffset;
|
|
const void FAR0 * sectorData =
|
|
vol.tl.mapSector(vol.tl.rec,vol.bootSectorNo + ioreq->irSectorNo,&cardOffset);
|
|
|
|
if (sectorData) {
|
|
if(sectorData==dataErrorToken)
|
|
return flDataError;
|
|
|
|
ioreq->irCount = cardOffset;
|
|
return flOK;
|
|
}
|
|
else
|
|
return flSectorNotFound;
|
|
}
|
|
|
|
#endif /* NO_PHYSICAL_IO */
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* g e t B P B */
|
|
/* */
|
|
/* Reads the BIOS Parameter Block from the boot sector */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irHandle : Drive number (0, 1, ...) */
|
|
/* irData : Address of user buffer to read BPB into */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus getBPB(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
BPB FAR1 *userBPB = (BPB FAR1 *) ioreq->irData;
|
|
DOSBootSector FAR0 *bootSector;
|
|
|
|
bootSector = (DOSBootSector FAR0 *) findSector(&vol,vol.bootSectorNo);
|
|
if(bootSector == NULL)
|
|
return flSectorNotFound;
|
|
if(bootSector==dataErrorToken)
|
|
return flDataError;
|
|
|
|
*userBPB = bootSector->bpb;
|
|
return flOK;
|
|
}
|
|
|
|
#ifndef FL_READ_ONLY
|
|
#ifdef WRITE_PROTECTION
|
|
/*----------------------------------------------------------------------*/
|
|
/* c h a n g e P a s s w o r d */
|
|
/* */
|
|
/* Change password for write protectipon. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus changePassword(Volume vol)
|
|
{
|
|
PartitionTable partitionTable;
|
|
IOreq ioreq;
|
|
FLStatus status;
|
|
#ifdef SCATTER_GATHER
|
|
void FAR1 *iovec[1];
|
|
#endif
|
|
|
|
ioreq.irHandle=(unsigned)(&vol-vols);
|
|
ioreq.irSectorNo=0-(int)vol.bootSectorNo;
|
|
ioreq.irSectorCount=1;
|
|
#ifdef SCATTER_GATHER
|
|
iovec[0] = (void FAR1 *) &partitionTable;
|
|
ioreq.irData = (void FAR1 *) iovec;
|
|
#else
|
|
ioreq.irData=&partitionTable;
|
|
#endif
|
|
if((status=absRead(&vol,&ioreq))!=flOK)
|
|
return status;
|
|
toUNAL4(partitionTable.passwordInfo[0], 0);
|
|
toUNAL4(partitionTable.passwordInfo[1],vol.password[0]);
|
|
toUNAL4(partitionTable.passwordInfo[2],vol.password[1]);
|
|
|
|
vol.flags &= ~VOLUME_WRITE_PROTECTED;
|
|
|
|
return absWrite(&vol,&ioreq);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* w r i t e P r o t e c t */
|
|
/* */
|
|
/* Put and remove write protection from the volume */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irHandle : Drive number ( 0,1,2... ) */
|
|
/* irFlags : FL_PROTECT = place protection */
|
|
/* FL_UNPROTECT = remove protection */
|
|
/* FL_UNLOCK = remove protection until next dismount */
|
|
/* irData : password (8 bytes) */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus writeProtect(Volume vol,IOreq FAR2*ioreq)
|
|
{
|
|
FLStatus status=flWriteProtect;
|
|
dword *flData=(dword *)ioreq->irData;
|
|
dword passCode1 = flData[0] ^ SCRAMBLE_KEY_1;
|
|
dword passCode2 = flData[1] ^ SCRAMBLE_KEY_2;
|
|
|
|
switch (ioreq->irFlags) {
|
|
|
|
case FL_UNLOCK: /* unlock volume */
|
|
if((vol.password[0] == passCode1 && vol.password[1] == passCode2)||
|
|
(vol.password[0] == 0 && vol.password[1] == 0))
|
|
{
|
|
vol.flags &= ~VOLUME_WRITE_PROTECTED;
|
|
status=flOK;
|
|
}
|
|
else
|
|
status=flWriteProtect;
|
|
break;
|
|
|
|
case FL_UNPROTECT: /* remove password */
|
|
if(vol.password[0] == passCode1 && vol.password[1] == passCode2)
|
|
{
|
|
vol.password[0] = vol.password[1] = 0;
|
|
status = changePassword(&vol);
|
|
}
|
|
else
|
|
status=flWriteProtect;
|
|
break;
|
|
|
|
case FL_PROTECT: /* set password */
|
|
if(vol.password[0] == 0 && vol.password[1] == 0)
|
|
{
|
|
vol.password[0] = passCode1;
|
|
vol.password[1] = passCode2;
|
|
status = changePassword(&vol);
|
|
vol.flags|=VOLUME_WRITE_PROTECTED;
|
|
}
|
|
else
|
|
status=flWriteProtect;
|
|
break;
|
|
|
|
default:
|
|
status = flGeneralFailure;
|
|
}
|
|
return status;
|
|
}
|
|
#endif /* WRITE_PROTECTION */
|
|
|
|
#endif /* FL_READ_ONLY */
|
|
|
|
#endif /* ABS_READ_WRITE */
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* s o c k e t I n f o */
|
|
/* */
|
|
/* Get socket Information (window base address) */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* baseAddress : pointer to receive window base address */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus socketInfo(Volume vol, dword FAR2 *baseAddress)
|
|
{
|
|
*baseAddress = (long)(vol.socket->window.baseAddress) << 12;
|
|
return flOK;
|
|
}
|
|
|
|
#ifdef FL_LOW_LEVEL
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* g e t P h y s i c a l I n f o */
|
|
/* */
|
|
/* Get physical information of the media. The information includes */
|
|
/* JEDEC ID, unit size and media size. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irData : Address of user buffer to read physical */
|
|
/* information into. */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/* irLength : Physical base address of device */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus getPhysicalInfo(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
PhysicalInfo FAR2 *physicalInfo = (PhysicalInfo FAR2 *)ioreq->irData;
|
|
|
|
physicalInfo->type = vol.flash->type;
|
|
physicalInfo->unitSize = vol.flash->erasableBlockSize;
|
|
physicalInfo->mediaSize = vol.flash->chipSize * vol.flash->noOfChips;
|
|
physicalInfo->chipSize = vol.flash->chipSize;
|
|
physicalInfo->interleaving = vol.flash->interleaving;
|
|
switch(vol.flash->mediaType) {
|
|
case NOT_DOC_TYPE:
|
|
physicalInfo->mediaType = FL_NOT_DOC;
|
|
break;
|
|
case DOC_TYPE :
|
|
physicalInfo->mediaType = FL_DOC;
|
|
break;
|
|
case MDOC_TYPE :
|
|
physicalInfo->mediaType = FL_MDOC;
|
|
break;
|
|
case MDOCP_TYPE :
|
|
physicalInfo->mediaType = FL_MDOCP;
|
|
break;
|
|
case DOC2000TSOP_TYPE :
|
|
physicalInfo->mediaType = FL_DOC2000TSOP;
|
|
break;
|
|
case MDOCP_16_TYPE :
|
|
physicalInfo->mediaType = FL_MDOCP_16;
|
|
break;
|
|
}
|
|
socketInfo(&vol,(dword FAR2 *) &(ioreq->irLength));
|
|
return flOK;
|
|
}
|
|
|
|
#ifndef NO_PHYSICAL_IO
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* p h y s i c a l R e a d */
|
|
/* */
|
|
/* Read from a physical address. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irAddress : Physical address to read from. */
|
|
/* irByteCount : Number of bytes to read. */
|
|
/* irData : Address of user buffer to read into. */
|
|
/* irFlags : Mode of the operation. */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus physicalRead(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
/* check that we are reading whithin the media boundaries */
|
|
if (ioreq->irAddress + (long)ioreq->irByteCount > (long)vol.flash->chipSize *
|
|
vol.flash->noOfChips)
|
|
return flBadParameter;
|
|
|
|
/* We don't read accross a unit boundary */
|
|
if ((long)ioreq->irByteCount > (long)(vol.flash->erasableBlockSize -
|
|
(ioreq->irAddress % vol.flash->erasableBlockSize)))
|
|
return flBadParameter;
|
|
|
|
checkStatus(vol.flash->read(vol.flash, ioreq->irAddress, ioreq->irData,
|
|
(word)ioreq->irByteCount, (word)ioreq->irFlags));
|
|
return flOK;
|
|
}
|
|
|
|
#ifndef FL_READ_ONLY
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* p h y s i c a l W r i t e */
|
|
/* */
|
|
/* Write to a physical address. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irAddress : Physical address to write to. */
|
|
/* irByteCount : Number of bytes to write. */
|
|
/* irData : Address of user buffer to write from. */
|
|
/* irFlags : Mode of the operation. */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus physicalWrite(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
/* check that we are writing whithin the media boundaries */
|
|
if (ioreq->irAddress + (long)ioreq->irByteCount > (long)(vol.flash->chipSize *
|
|
vol.flash->noOfChips))
|
|
return flBadParameter;
|
|
|
|
/* We don't write accross a unit boundary */
|
|
if (ioreq->irByteCount > (long)(vol.flash->erasableBlockSize -
|
|
(ioreq->irAddress % vol.flash->erasableBlockSize)))
|
|
return flBadParameter;
|
|
|
|
checkStatus(vol.flash->write(vol.flash, ioreq->irAddress, ioreq->irData,
|
|
(dword)ioreq->irByteCount, (word)ioreq->irFlags));
|
|
return flOK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* p h y s i c a l E r a s e */
|
|
/* */
|
|
/* Erase physical units. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irUnitNo : First unit to erase. */
|
|
/* irUnitCount : Number of units to erase. */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus physicalErase(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
if (ioreq->irUnitNo + (long)ioreq->irUnitCount > (long)
|
|
(vol.flash->chipSize * vol.flash->noOfChips / vol.flash->erasableBlockSize))
|
|
return flBadParameter;
|
|
|
|
checkStatus(vol.flash->erase(vol.flash, (word)ioreq->irUnitNo, (word)ioreq->irUnitCount));
|
|
return flOK;
|
|
}
|
|
#endif /* NO_PHYSICAL_IO */
|
|
#endif /* FL_READ_ONLY */
|
|
|
|
|
|
#ifndef NO_IPL_CODE
|
|
/*----------------------------------------------------------------------*/
|
|
/* r e a d I P L */
|
|
/* */
|
|
/* Read IPL to user buffer. */
|
|
/* */
|
|
/* Note : Read length must be a multiplication of 512 bytes */
|
|
/* Note : Causes DiskOnChip Millennium Plus to download (i,e protection */
|
|
/* key will be removed from all partitions. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* flash : Pointer identifying flash medium of the volume */
|
|
/* irHandle : Socket number ( 0,1,2... ) */
|
|
/* buf : User buffer to read into */
|
|
/* bufLen : Size of user buffer */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus readIPL(FLFlash* flash, byte FAR1 * buf , dword bufLen)
|
|
{
|
|
FLStatus status;
|
|
dword secondCopyOffset = 1024;
|
|
|
|
if(bufLen & 512)
|
|
{
|
|
DEBUG_PRINT(("ERROR - Must read a multiplication of 512 bytes.\r\n"));
|
|
return flBadLength;
|
|
}
|
|
|
|
switch (flash->mediaType)
|
|
{
|
|
case MDOCP_TYPE: /* have a special place for the IPL */
|
|
case MDOCP_16_TYPE:
|
|
if (flash->readIPL != NULL)
|
|
{
|
|
checkStatus(flash->readIPL(flash,buf,(word)bufLen));
|
|
return flOK;
|
|
}
|
|
break;
|
|
case MDOC_TYPE:
|
|
if(bufLen != 512)
|
|
{
|
|
DEBUG_PRINT(("ERROR - DiskOnChip Millennium 8M has only 512 Bytes of XIP.\r\n"));
|
|
return flBadLength;
|
|
}
|
|
secondCopyOffset = 512;
|
|
|
|
case DOC2000TSOP_TYPE: /* Have a special place for the IPL */
|
|
if(bufLen > 1024)
|
|
{
|
|
DEBUG_PRINT(("ERROR - DiskOnChip 2000 TSOP has only 1024 Bytes of XIP.\r\n"));
|
|
return flBadLength;
|
|
}
|
|
if(flash->read != NULL)
|
|
{
|
|
status = flash->read(flash,0,buf,bufLen,EDC);
|
|
if(status != flOK)
|
|
return flash->read(flash,secondCopyOffset,buf,bufLen,EDC);
|
|
return status;
|
|
}
|
|
break;
|
|
default :
|
|
if(bufLen != 512)
|
|
{
|
|
DEBUG_PRINT(("ERROR - DiskOnChip 2000 has only 512 Bytes of XIP.\r\n"));
|
|
return flBadLength;
|
|
}
|
|
if(flash->win != NULL)
|
|
{
|
|
tffscpy(buf,(const void FAR1*)flash->win,bufLen);
|
|
}
|
|
break;
|
|
}
|
|
return flGeneralFailure;
|
|
}
|
|
|
|
#ifndef FL_READ_ONLY
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* w r i t e I P L */
|
|
/* */
|
|
/* Write IPL to the proper media location */
|
|
/* */
|
|
/* Parameters: */
|
|
/* flash : Pointer identifying flash medium of the volume */
|
|
/* irHandle : Socket number ( 0,1,2... ) */
|
|
/* buf : User buffer containin data to write to the IPL */
|
|
/* bufLen : Size of user buffer */
|
|
/* flags : FL_IPL_MODE_NORMAL : None Strong Arm mode */
|
|
/* FL_IPL_DOWNLOAD : Download new IPL when done */
|
|
/* FL_IPL_MODE_SA : Strong Arm mode */
|
|
/* FL_IPL_MODE_XSCALE : X-Scale mode */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus writeIPL(FLFlash* flash, byte FAR1 * buf , dword bufLen , unsigned flags)
|
|
{
|
|
switch (flash->mediaType)
|
|
{
|
|
case DOC2000TSOP_TYPE: /* Have a special place for the IPL */
|
|
case MDOCP_TYPE :
|
|
case MDOCP_16_TYPE :
|
|
if (flash->writeIPL != NULL)
|
|
return (flash->writeIPL(flash,buf,(word)bufLen,0,flags));
|
|
DFORMAT_PRINT(("ERROR - MTD does not support write IPL (Please reconfigure MTD).\r\n"));
|
|
break;
|
|
case MDOC_TYPE:
|
|
DFORMAT_PRINT(("ERROR - DiskOnChip Millennium does not support write IPL, use the /BDFK flag.\r\n"));
|
|
break;
|
|
default :
|
|
DFORMAT_PRINT(("ERROR - DiskOnChip 2000 does not support a writiable IPL.\r\n"));
|
|
break;
|
|
}
|
|
return flFeatureNotSupported;
|
|
}
|
|
#endif /* FL_READ_ONLY */
|
|
#endif /* NO_IPL_CODE */
|
|
|
|
#ifndef NO_INQUIRE_CAPABILITIES
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* i n q u i r e C a p a b i l i t i e s */
|
|
/* */
|
|
/* Get the specific device S/W and H/W capabilities */
|
|
/* */
|
|
/* Parameters: */
|
|
/* flash : Record discribing the media */
|
|
/* 4 LSB - Socket number */
|
|
/* capability : Enumarator representing the capability */
|
|
/* Returns: */
|
|
/* capability : CAPABILITY_SUPPORTED if the capability is */
|
|
/* supported */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static void inquireCapabilities(FLFlash* flash , FLCapability FAR2* capability)
|
|
{
|
|
FLCapability inquiredCapability = *capability;
|
|
|
|
*capability = CAPABILITY_NOT_SUPPORTED;
|
|
|
|
switch (inquiredCapability)
|
|
{
|
|
#ifdef HW_OTP
|
|
case SUPPORT_UNERASABLE_BBT:
|
|
case SUPPORT_OTP_AREA:
|
|
if(flash->otpSize != NULL)
|
|
*capability = CAPABILITY_SUPPORTED;
|
|
break;
|
|
case SUPPORT_CUSTOMER_ID:
|
|
case SUPPORT_UNIQUE_ID:
|
|
if(flash->getUniqueId != NULL)
|
|
*capability = CAPABILITY_SUPPORTED;
|
|
break;
|
|
#endif /* HW_OTP */
|
|
case SUPPORT_MULTIPLE_BDTL_PARTITIONS:
|
|
case SUPPORT_MULTIPLE_BINARY_PARTITIONS:
|
|
if(flash->flags & INFTL_ENABLED)
|
|
*capability = CAPABILITY_SUPPORTED;
|
|
break;
|
|
|
|
#ifdef HW_PROTECTION
|
|
case SUPPORT_HW_PROTECTION:
|
|
case SUPPORT_HW_LOCK_KEY:
|
|
if(flash->protectionKeyInsert != NULL)
|
|
*capability = CAPABILITY_SUPPORTED;
|
|
break;
|
|
#endif /* HW_PROTECTION */
|
|
case SUPPORT_DEEP_POWER_DOWN_MODE:
|
|
if(flash->enterDeepPowerDownMode != NULL)
|
|
*capability = CAPABILITY_SUPPORTED;
|
|
break;
|
|
case SUPPORT_WRITE_IPL_ROUTINE:
|
|
if((flash->mediaType == DOC2000TSOP_TYPE) ||
|
|
(flash->mediaType == MDOC_TYPE))
|
|
*capability = CAPABILITY_SUPPORTED;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#endif /* NO_INQUIRE_CAPABILITIES */
|
|
#endif /* FL_LOW_LEVEL */
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l B u i l d G e o m e t r y */
|
|
/* */
|
|
/* Get C/H/S information of the disk according to number of sectors. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* capacity : Number of Sectors in Volume */
|
|
/* cylinders : Pointer to Number of Cylinders */
|
|
/* heads : Pointer to Number of Heads */
|
|
/* sectors : Pointer to Number of Sectors per Track */
|
|
/* oldFormat : True for one sector per culoster */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void NAMING_CONVENTION flBuildGeometry(dword capacity, dword FAR2 *cylinders,
|
|
dword FAR2 *heads,dword FAR2 *sectors, FLBoolean oldFormat)
|
|
{
|
|
dword temp;
|
|
|
|
*cylinders = 1024; /* Set number of cylinders to max value */
|
|
|
|
if (oldFormat == TRUE)
|
|
{
|
|
*sectors = 62L; /* Max out number of sectors per track */
|
|
temp = (*cylinders) * (*sectors); /* Compute divisor for heads */
|
|
(*heads) = capacity / temp; /* Compute value for number of heads */
|
|
if (capacity % temp) { /* If no remainder, done! */
|
|
(*heads)++; /* Else, increment number of heads */
|
|
temp = (*cylinders) * (*heads); /* Compute divisor for sectors */
|
|
(*sectors) = capacity / temp; /* Compute value for sectors per track */
|
|
if (capacity % temp) { /* If no remainder, done! */
|
|
(*sectors)++; /* Else, increment number of sectors */
|
|
temp = (*heads) * (*sectors); /* Compute divisor for cylinders */
|
|
(*cylinders) = capacity / temp; /* Compute number of cylinders */
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*heads = 16L; /* Max out number of heads */
|
|
temp = (*cylinders) * (*heads); /* Compute divisor for heads */
|
|
*sectors = capacity / temp; /* Compute value for sectors per track */
|
|
while (*sectors > 0x3f ){ /* While number of sectors too big */
|
|
*heads *= 2; /* use one more head */
|
|
temp = (*cylinders) * (*heads); /* Recompute divisor for heads */
|
|
*sectors = capacity / temp; /* Recompute sectors per track */
|
|
}
|
|
if (capacity % temp) { /* If no remainder, done! */
|
|
(*sectors)++; /* Else, increment number of sectors */
|
|
temp = (*cylinders) * (*sectors); /* Compute divisor for heads */
|
|
*heads = capacity / temp; /* Compute value for heads */
|
|
if (capacity % temp) { /* If no remainder, done! */
|
|
(*heads)++; /* Else, increment number of heads */
|
|
temp = (*heads) * (*sectors); /* Compute divisor for cylinders */
|
|
*cylinders = (dword)(capacity / temp); /* Compute number of cylinders */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* v o l u m e I n f o */
|
|
/* */
|
|
/* Get general volume Information. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* vol : Pointer identifying drive */
|
|
/* irHandle : Drive number (0, 1, ...) */
|
|
/* irData : pointer to VolumeInfoRecord */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static FLStatus volumeInfo(Volume vol, IOreq FAR2 *ioreq)
|
|
{
|
|
VolumeInfoRecord FAR2 *info = (VolumeInfoRecord FAR2 *)(ioreq->irData);
|
|
#ifdef FL_LOW_LEVEL
|
|
IOreq ioreq2;
|
|
PhysicalInfo physicalInfo;
|
|
char wasLowLevelMounted = 1;
|
|
#endif
|
|
TLInfo tlInfo;
|
|
#ifdef FL_LOW_LEVEL
|
|
dword eraseCyclesPerUnit;
|
|
#endif /* FL_LOW_LEVEL */
|
|
|
|
#ifdef FL_LOW_LEVEL
|
|
ioreq2.irHandle = ioreq->irHandle;
|
|
if (!(vol.flags & VOLUME_LOW_LVL_MOUNTED)) {
|
|
checkStatus(mountLowLevel(&vol));
|
|
wasLowLevelMounted = 0;
|
|
}
|
|
ioreq2.irData = &physicalInfo;
|
|
checkStatus(getPhysicalInfo(&vol, &ioreq2));
|
|
info->flashType = physicalInfo.type;
|
|
info->physicalUnitSize = (unsigned short)physicalInfo.unitSize;
|
|
info->physicalSize = physicalInfo.mediaSize;
|
|
info->DOCType = physicalInfo.mediaType;
|
|
#endif /* FL_LOW_LEVEL */
|
|
tffsset(info->driverVer,0,sizeof(info->driverVer));
|
|
tffsset(info->OSAKVer,0,sizeof(info->OSAKVer));
|
|
tffscpy(info->driverVer,driverVersion,
|
|
TFFSMIN(sizeof(info->driverVer),sizeof(driverVersion)));
|
|
tffscpy(info->OSAKVer,OSAKVersion,
|
|
TFFSMIN(sizeof(info->OSAKVer),sizeof(OSAKVersion)));
|
|
checkStatus(socketInfo(&vol, &(info->baseAddress)));
|
|
checkStatus(vol.tl.getTLInfo(vol.tl.rec,&tlInfo));
|
|
info->logicalSectors = tlInfo.sectorsInVolume;
|
|
info->bootAreaSize = tlInfo.bootAreaSize;
|
|
|
|
#ifdef ABS_READ_WRITE
|
|
flBuildGeometry( tlInfo.sectorsInVolume,
|
|
(dword FAR2 *)&(info->cylinders),
|
|
(dword FAR2 *)&(info->heads),
|
|
(dword FAR2 *)&(info->sectors),FALSE);
|
|
#endif /* ABS_READ_WRITE */
|
|
|
|
#ifdef FL_LOW_LEVEL
|
|
|
|
eraseCyclesPerUnit = vol.flash->maxEraseCycles;
|
|
info->lifeTime = (char)(((tlInfo.eraseCycles /
|
|
(eraseCyclesPerUnit * (physicalInfo.mediaSize / physicalInfo.unitSize)))
|
|
% 10) + 1);
|
|
if(!wasLowLevelMounted)
|
|
dismountLowLevel(&vol);
|
|
#endif /* FL_LOW_LEVEL */
|
|
return flOK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* b d C a l l */
|
|
/* */
|
|
/* Common entry-point to all file-system functions. Macros are */
|
|
/* to call individual function, which are separately described below. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* function : file-system function code (listed below) */
|
|
/* ioreq : IOreq structure */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus NAMING_CONVENTION bdCall(FLFunctionNo functionNo, IOreq FAR2 *ioreq)
|
|
{
|
|
Volume vol = NULL;
|
|
FLStatus status;
|
|
byte volNo;
|
|
#if defined(FILES) && FILES>0
|
|
File *file;
|
|
#endif
|
|
byte socket = FL_GET_SOCKET_FROM_HANDLE(ioreq);
|
|
byte partition = FL_GET_PARTITION_FROM_HANDLE(ioreq);
|
|
byte curPartitionForEnvVars;
|
|
|
|
/***********************************************/
|
|
/*** ***/
|
|
/*** find the volume record to work on ***/
|
|
/*** ***/
|
|
/***********************************************/
|
|
|
|
if (initDone == FALSE)
|
|
checkStatus(flInit());
|
|
|
|
/** ori - We are not taking mutex befre cheking fileTable */
|
|
|
|
/**************************************/
|
|
/* working with open files operations */
|
|
/**************************************/
|
|
|
|
#if defined(FILES) && FILES>0
|
|
/* Verify file handle if applicable */
|
|
if ((functionNo < INDEX_OPENFILES_END) &&
|
|
((functionNo != FL_FIND_FILE)||(ioreq->irFlags & FIND_BY_HANDLE)))
|
|
{
|
|
if ((ioreq->irHandle < FILES) &&
|
|
(fileTable[ioreq->irHandle].flags & FILE_IS_OPEN))
|
|
{
|
|
file = fileTable + ioreq->irHandle;
|
|
pVol = file->fileVol;
|
|
socket = vol.tl.socketNo;
|
|
partition = vol.tl.partitionNo;
|
|
}
|
|
else
|
|
{
|
|
return flBadFileHandle;
|
|
}
|
|
}
|
|
|
|
#endif /* FILES>0 */
|
|
|
|
/* Set environment variable current partition. */
|
|
curPartitionForEnvVars = partition;
|
|
|
|
|
|
/****************************************************/
|
|
/* None files operations are divided into 3 groups: */
|
|
/* 1. Uses the specific partition volume record. */
|
|
/* 2. Must be called with partition number 0. */
|
|
/* 3. Must use partition number 0 and ignore */
|
|
/* the given partition (binary operations). */
|
|
/****************************************************/
|
|
|
|
if (pVol == NULL) /* irHandle is drive no. */
|
|
{
|
|
|
|
/* Handle sanity check */
|
|
|
|
if ((socket >= noOfSockets) ||
|
|
(partition >= MAX_TL_PARTITIONS))
|
|
return flBadDriveHandle;
|
|
|
|
volNo = handleConversionTable[socket][partition];
|
|
|
|
/* Some operation must not be checked ONLY for socket sanity */
|
|
|
|
if((functionNo < INDEX_BINARY_END) && /* Group 3 */
|
|
(functionNo > INDEX_BINARY_START))
|
|
{
|
|
volNo = socket;
|
|
|
|
/* Binary partitions are numbered after BDTL partitions */
|
|
curPartitionForEnvVars = (byte)(MAX_TL_PARTITIONS+partition);
|
|
}
|
|
|
|
/* The rest must be checked for socket and volume sanity */
|
|
|
|
else
|
|
{
|
|
if (volNo == INVALID_VOLUME_NUMBER) /* Group 1 + 2 */
|
|
return flBadDriveHandle;
|
|
|
|
/* Some operation must be called with partition 0 */
|
|
|
|
if ((functionNo > INDEX_NEED_PARTITION_0_START) && /* Group 2 */
|
|
(functionNo < INDEX_NEED_PARTITION_0_END))
|
|
{
|
|
if(partition != 0)
|
|
{
|
|
return flBadDriveHandle;
|
|
}
|
|
else /* Use general verify write environement variable */
|
|
{
|
|
curPartitionForEnvVars = (MAX_TL_PARTITIONS<<1)-1;
|
|
}
|
|
}
|
|
}
|
|
pVol = &vols[volNo];
|
|
}
|
|
|
|
/********************************************************************/
|
|
/*** ***/
|
|
/*** Volume record has been found. Now verify that the volume ***/
|
|
/*** record is ready for the specific operation. ***/
|
|
/*** ***/
|
|
/********************************************************************/
|
|
|
|
status = setBusy(&vol,FL_ON,curPartitionForEnvVars); /* Let everyone know we are here */
|
|
|
|
/*******************************/
|
|
/* Verify S/W write protection */
|
|
/*******************************/
|
|
|
|
#if defined(WRITE_PROTECTION)&& !defined(FL_READ_ONLY)
|
|
if(vol.flags&VOLUME_WRITE_PROTECTED)
|
|
if(
|
|
#if defined(FILES) && FILES>0
|
|
((functionNo > INDEX_WRITE_FILE_START) &&
|
|
(functionNo < FL_LAST_FAT_FUNCTION)) ||
|
|
#endif /* FILES > 0 */
|
|
#ifdef FORMAT_VOLUME
|
|
(functionNo==BD_FORMAT_VOLUME) ||
|
|
(functionNo==BD_FORMAT_PHYSICAL_DRIVE) ||
|
|
(functionNo==BD_FORMAT_LOGICAL_DRIVE) ||
|
|
#endif /* FORMAT_VOLUME */
|
|
#ifdef WRITE_EXB_IMAGE
|
|
(functionNo==FL_PLACE_EXB) ||
|
|
#endif /* WRITE_EXB_IMAGE */
|
|
(functionNo==FL_DEFRAGMENT_VOLUME) ||
|
|
#ifdef ABS_READ_WRITE
|
|
(functionNo==FL_ABS_WRITE) ||
|
|
(functionNo==FL_ABS_DELETE) ||
|
|
#endif /* ABS_READ_WRITE */
|
|
#ifdef FL_LOW_LEVEL
|
|
(functionNo==FL_PHYSICAL_WRITE) ||
|
|
(functionNo==FL_PHYSICAL_ERASE) ||
|
|
#endif /* FL_LOW_LEVEL */
|
|
#ifdef VERIFY_VOLUME
|
|
(functionNo==FL_VERIFY_VOLUME) ||
|
|
#endif /* VERIFY_VOLUME */
|
|
0)
|
|
{
|
|
status = flWriteProtect;
|
|
goto flCallExit;
|
|
}
|
|
|
|
#endif /* WRITE_PROTECTION && !FL_READ_ONLY */
|
|
|
|
/***********************************************/
|
|
/* Binary partition operations */
|
|
/* Low level mount and direct call the routine */
|
|
/***********************************************/
|
|
|
|
#ifdef BDK_ACCESS
|
|
if ((functionNo > INDEX_BINARY_START) &&
|
|
(functionNo < INDEX_BINARY_END ) )
|
|
{
|
|
#ifdef WRITE_EXB_IMAGE
|
|
if ((functionNo != FL_BINARY_PROTECTION_INSERT_KEY) &&
|
|
(functionNo != FL_BINARY_PROTECTION_REMOVE_KEY))
|
|
vol.moduleNo = INVALID_MODULE_NO; /* Stop place EXB operation */
|
|
#endif
|
|
/* Mount flash and call binary module to proccess request */
|
|
|
|
if (!(pVol->flags & VOLUME_LOW_LVL_MOUNTED))
|
|
status = mountLowLevel(&vol);
|
|
if (status == flOK)
|
|
status = bdkCall(functionNo,ioreq,pVol->flash);
|
|
goto flCallExit;
|
|
}
|
|
#endif /* BDK_ACCESS */
|
|
|
|
/***********************************/
|
|
/* None binary routine */
|
|
/* Nag about mounting if necessary */
|
|
/***********************************/
|
|
|
|
switch (functionNo) {
|
|
#if FILES > 0
|
|
case FL_LAST_FAT_FUNCTION:
|
|
status = flBadFunction;
|
|
goto flCallExit;
|
|
#endif
|
|
|
|
/* Pre mount routine - Make sure the volume is low level disMounted */
|
|
|
|
case FL_ABS_MOUNT:
|
|
case FL_MOUNT_VOLUME:
|
|
#ifndef FL_READ_ONLY
|
|
#ifdef FORMAT_VOLUME
|
|
case BD_FORMAT_VOLUME:
|
|
case BD_FORMAT_LOGICAL_DRIVE:
|
|
#endif /* FORMAT_VOLUME */
|
|
#endif /* FL_READ_ONLY */
|
|
#ifdef FL_LOW_LEVEL
|
|
if (vol.flags & VOLUME_LOW_LVL_MOUNTED)
|
|
dismountLowLevel(&vol); /* mutual exclusive mounting */
|
|
#endif /* FL_LOW_LEVEL */
|
|
break;
|
|
|
|
/* Physical operation must have the device low level (MTD) mounted */
|
|
|
|
/* Do not need any special operation */
|
|
|
|
case FL_UPDATE_SOCKET_PARAMS:
|
|
case FL_COUNT_VOLUMES:
|
|
#if (defined(FORMAT_VOLUME) && !defined(FL_READ_ONLY))
|
|
case FL_WRITE_BBT:
|
|
#endif
|
|
#ifdef HW_PROTECTION
|
|
case FL_PROTECTION_GET_TYPE:
|
|
case FL_PROTECTION_REMOVE_KEY:
|
|
case FL_PROTECTION_INSERT_KEY:
|
|
#ifndef FL_READ_ONLY
|
|
case FL_PROTECTION_SET_LOCK:
|
|
case FL_PROTECTION_CHANGE_KEY:
|
|
case FL_PROTECTION_CHANGE_TYPE:
|
|
#endif /* FL_READ_ONLY */
|
|
#endif /* HW_PROTECTION */
|
|
#ifdef QUICK_MOUNT_FEATURE
|
|
case FL_CLEAR_QUICK_MOUNT_INFO:
|
|
#endif /* QUICK_MOUNT_FEATURE */
|
|
break;
|
|
|
|
/* MTD must be mounted first */
|
|
|
|
#ifdef FL_LOW_LEVEL
|
|
|
|
/* Some physical operation must not be done while abs mounted */
|
|
case FL_GET_PHYSICAL_INFO:
|
|
case FL_PHYSICAL_READ:
|
|
#ifndef FL_READ_ONLY
|
|
case FL_PHYSICAL_WRITE:
|
|
case FL_PHYSICAL_ERASE:
|
|
#endif /* FL_READ_ONLY */
|
|
#ifndef BDK_ACCESS
|
|
#ifdef MULTI_DOC
|
|
#ifdef ENVIRONMENT_VARS
|
|
if (flUseMultiDoc == FL_ON)
|
|
#endif
|
|
{
|
|
volNo = handleConversionTable[0][0];
|
|
if ((volNo != INVALID_VOLUME_NUMBER) &&
|
|
(pVol[volNo].flags & VOLUME_ABS_MOUNTED))
|
|
#else
|
|
{
|
|
if(vol.flags & VOLUME_ABS_MOUNTED)
|
|
#endif
|
|
{
|
|
status = flGeneralFailure; /* mutual exclusive mounting */
|
|
goto flCallExit;
|
|
}
|
|
}
|
|
#endif /* BDK_ACCESS */
|
|
#ifndef NO_INQUIRE_CAPABILITIES
|
|
case FL_INQUIRE_CAPABILITIES:
|
|
#endif /* NO_INQUIRE_CAPABILITIES */
|
|
case FL_DEEP_POWER_DOWN_MODE:
|
|
#ifdef HW_OTP
|
|
case FL_OTP_SIZE:
|
|
case FL_OTP_READ:
|
|
#ifndef FL_READ_ONLY
|
|
case FL_OTP_WRITE:
|
|
#endif /* FL_READ_ONLY */
|
|
case FL_UNIQUE_ID:
|
|
case FL_CUSTOMER_ID:
|
|
#endif /* HW_OTP */
|
|
#ifndef NO_IPL_CODE
|
|
case FL_READ_IPL:
|
|
#ifndef FL_READ_ONLY
|
|
case FL_WRITE_IPL:
|
|
#endif /* FL_READ_ONLY */
|
|
#endif /* NO_IPL_CODE */
|
|
#ifndef FL_READ_ONLY
|
|
#ifdef WRITE_EXB_IMAGE
|
|
case FL_PLACE_EXB:
|
|
#endif /* WRITE_EXB_IMAGE */
|
|
#ifdef FORMAT_VOLUME
|
|
case BD_FORMAT_PHYSICAL_DRIVE:
|
|
#endif /* FORMAT_VOLUME */
|
|
#endif /* FL_READ_ONLY */
|
|
|
|
if (!(vol.flags & VOLUME_LOW_LVL_MOUNTED))
|
|
{
|
|
status = mountLowLevel(&vol); /* automatic low level mounting */
|
|
}
|
|
else
|
|
{
|
|
status = flOK;
|
|
#ifndef FIXED_MEDIA
|
|
status = flMediaCheck(vol.socket);
|
|
if (status == flDiskChange)
|
|
status = mountLowLevel(&vol); /* card was changed, remount */
|
|
#endif /* FIXED_MEDIA */
|
|
}
|
|
if (status != flOK)
|
|
{
|
|
dismountLowLevel(&vol);
|
|
goto flCallExit;
|
|
}
|
|
break;
|
|
#endif /* FL_LOW_LEVEL */
|
|
|
|
/* Check for abs mount */
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
if (vol.flags & VOLUME_ABS_MOUNTED)
|
|
{
|
|
#ifndef NT5PORT
|
|
FLStatus status = flOK;
|
|
#else /*NT5PORT*/
|
|
FLStatus istatus = flOK;
|
|
#endif /*NT5PORT*/
|
|
|
|
#ifndef FIXED_MEDIA
|
|
#ifndef NT5PORT
|
|
status = flMediaCheck(vol.socket);
|
|
#else /*NT5PORT*/
|
|
istatus = flMediaCheck(vol.socket);
|
|
#endif /*NT5PORT*/
|
|
#endif /*FIXED_MEDIA*/
|
|
|
|
#ifndef NT5PORT
|
|
if (status != flOK)
|
|
#else /*NT5PORT*/
|
|
if (istatus != flOK)
|
|
#endif /*NT5PORT*/
|
|
dismountVolume(&vol);
|
|
}
|
|
if (!(vol.flags & VOLUME_ABS_MOUNTED)
|
|
#if defined(FILES) && FILES>0
|
|
&& (functionNo > FL_LAST_FAT_FUNCTION)
|
|
#endif
|
|
)
|
|
{
|
|
status = flNotMounted;
|
|
goto flCallExit;
|
|
}
|
|
|
|
/* We know that the tl is abs mounted (except for files )
|
|
now check for high level mounted */
|
|
|
|
if (!( vol.flags & VOLUME_MOUNTED ) &&
|
|
( functionNo != FL_DISMOUNT_VOLUME ) &&
|
|
( functionNo != FL_CHECK_VOLUME ) &&
|
|
#ifndef FL_READ_ONLY
|
|
( functionNo != FL_DEFRAGMENT_VOLUME ) &&
|
|
#endif /* FL_READ_ONLY */
|
|
#ifdef ABS_READ_WRITE
|
|
( functionNo != FL_ABS_READ ) &&
|
|
( functionNo != FL_ABS_ADDRESS ) &&
|
|
#ifndef FL_READ_ONLY
|
|
( functionNo != FL_ABS_WRITE ) &&
|
|
( functionNo != FL_ABS_DELETE ) &&
|
|
#endif /* FL_READ_ONLY */
|
|
#endif /* ABS_READ_WRITE */
|
|
#if (defined(WRITE_PROTECTION) && !defined(FL_READ_ONLY))
|
|
( functionNo != FL_WRITE_PROTECTION ) &&
|
|
#endif /* WRITE_PROTECTION */
|
|
#ifdef VERIFY_VOLUME
|
|
( functionNo != FL_VERIFY_VOLUME ) &&
|
|
#endif /* VERIFY_VOLUME */
|
|
( functionNo != FL_READ_BBT ) &&
|
|
( functionNo != FL_SECTORS_IN_VOLUME ) &&
|
|
( functionNo != FL_VOLUME_INFO ))
|
|
{
|
|
status = flNotMounted;
|
|
goto flCallExit;
|
|
}
|
|
}
|
|
|
|
/*****************************************************/
|
|
/*** ***/
|
|
/*** The Volume record is already initialized. ***/
|
|
/*** Exceute the proper function. ***/
|
|
/*** ***/
|
|
/*****************************************************/
|
|
|
|
switch (functionNo) {
|
|
|
|
#if defined(FILES) && FILES > 0
|
|
#ifndef FL_READ_ONLY
|
|
case FL_FLUSH_BUFFER:
|
|
status = flushBuffer(&vol);
|
|
break;
|
|
#endif /* FL_READ_ONLY */
|
|
case FL_OPEN_FILE:
|
|
status = openFile(&vol,ioreq);
|
|
break;
|
|
|
|
case FL_CLOSE_FILE:
|
|
status = closeFile(file);
|
|
break;
|
|
#ifndef FL_READ_ONLY
|
|
#ifdef SPLIT_JOIN_FILE
|
|
case FL_JOIN_FILE:
|
|
status = joinFile(file, ioreq);
|
|
break;
|
|
|
|
case FL_SPLIT_FILE:
|
|
status = splitFile(file, ioreq);
|
|
break;
|
|
#endif
|
|
#endif /* FL_READ_ONLY */
|
|
case FL_READ_FILE:
|
|
status = readFile(file,ioreq);
|
|
break;
|
|
#ifndef FL_READ_ONLY
|
|
case FL_WRITE_FILE:
|
|
status = writeFile(file,ioreq);
|
|
break;
|
|
#endif
|
|
case FL_SEEK_FILE:
|
|
status = seekFile(file,ioreq);
|
|
break;
|
|
|
|
case FL_FIND_FILE:
|
|
status = findFile(&vol,file,ioreq);
|
|
break;
|
|
|
|
case FL_FIND_FIRST_FILE:
|
|
status = findFirstFile(&vol,ioreq);
|
|
break;
|
|
|
|
case FL_FIND_NEXT_FILE:
|
|
status = findNextFile(file,ioreq);
|
|
break;
|
|
|
|
case FL_GET_DISK_INFO:
|
|
status = getDiskInfo(&vol,ioreq);
|
|
break;
|
|
#ifndef FL_READ_ONLY
|
|
case FL_DELETE_FILE:
|
|
status = deleteFile(&vol,ioreq,FALSE);
|
|
break;
|
|
|
|
#ifdef RENAME_FILE
|
|
case FL_RENAME_FILE:
|
|
status = renameFile(&vol,ioreq);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef SUB_DIRECTORY
|
|
case FL_MAKE_DIR:
|
|
status = makeDir(&vol,ioreq);
|
|
break;
|
|
|
|
case FL_REMOVE_DIR:
|
|
status = deleteFile(&vol,ioreq,TRUE);
|
|
break;
|
|
#endif
|
|
#endif /* FL_READ_ONLY */
|
|
#endif /* FILES > 0 */
|
|
|
|
case FL_MOUNT_VOLUME:
|
|
status = mountVolume(&vol,&(ioreq->irFlags));
|
|
break;
|
|
|
|
case FL_DISMOUNT_VOLUME:
|
|
status = dismountVolume(&vol);
|
|
break;
|
|
|
|
case FL_CHECK_VOLUME:
|
|
status = flOK; /* If we got this far */
|
|
break;
|
|
|
|
case FL_UPDATE_SOCKET_PARAMS:
|
|
status = updateSocketParameters(flSocketOf(ioreq->irHandle), ioreq->irData);
|
|
break;
|
|
|
|
#ifndef NO_READ_BBT_CODE
|
|
case FL_READ_BBT:
|
|
if(vol.tl.readBBT != NULL)
|
|
{
|
|
status = vol.tl.readBBT(vol.tl.rec,(CardAddress FAR1 *)ioreq->irData,
|
|
&(ioreq->irLength),&(ioreq->irFlags));
|
|
}
|
|
else
|
|
{
|
|
status = flFeatureNotSupported;
|
|
}
|
|
break;
|
|
#endif /* NO_READ_BBT_CODE */
|
|
|
|
#ifndef FL_READ_ONLY
|
|
#ifdef DEFRAGMENT_VOLUME
|
|
case FL_DEFRAGMENT_VOLUME:
|
|
status = defragmentVolume(&vol,ioreq);
|
|
break;
|
|
#endif /* DEFRAGMENT_VOLUME */
|
|
|
|
#if defined (FORMAT_VOLUME) && !defined(FL_READ_ONLY)
|
|
case BD_FORMAT_VOLUME:
|
|
status = bdFormatVolume(&vol,ioreq);
|
|
break;
|
|
|
|
case BD_FORMAT_PHYSICAL_DRIVE:
|
|
status = bdFormatPhysicalDrive(&vol,ioreq);
|
|
break;
|
|
|
|
case BD_FORMAT_LOGICAL_DRIVE:
|
|
status = bdFormatLogicalDrive(&vol,ioreq);
|
|
break;
|
|
|
|
#endif /* FORMAT_VOLUME AND NOT FL_READ_ONLY */
|
|
#ifdef WRITE_EXB_IMAGE
|
|
case FL_PLACE_EXB:
|
|
status = placeExbByBuffer(&vol,(byte FAR1*)ioreq->irData,
|
|
ioreq->irLength,(word)ioreq->irWindowBase ,(word)ioreq->irFlags);
|
|
break;
|
|
|
|
#endif /* WRITE_EXB_IMAGE */
|
|
#endif /* FL_READ_ONLY */
|
|
|
|
case FL_SECTORS_IN_VOLUME:
|
|
status = sectorsInVolume(&vol,ioreq);
|
|
break;
|
|
|
|
case FL_ABS_MOUNT:
|
|
status = absMountVolume(&vol);
|
|
break;
|
|
|
|
#ifdef ABS_READ_WRITE
|
|
case FL_ABS_READ:
|
|
status = absRead(&vol,ioreq);
|
|
break;
|
|
|
|
#ifndef NO_PHYSICAL_IO
|
|
case FL_ABS_ADDRESS:
|
|
status = absAddress(&vol,ioreq);
|
|
break;
|
|
#endif /* NO_PHYSICAL_IO */
|
|
|
|
#ifndef FL_READ_ONLY
|
|
case FL_ABS_DELETE:
|
|
status = absDelete(&vol,ioreq);
|
|
break;
|
|
|
|
case FL_ABS_WRITE:
|
|
status = absWrite(&vol,ioreq);
|
|
break;
|
|
|
|
#endif /* FL_READ_ONLY */
|
|
|
|
case FL_GET_BPB:
|
|
status = getBPB(&vol,ioreq);
|
|
break;
|
|
|
|
#ifndef FL_READ_ONLY
|
|
#if (defined(WRITE_PROTECTION) && !defined(FL_READ_ONLY))
|
|
case FL_WRITE_PROTECTION :
|
|
status = writeProtect(&vol,ioreq);
|
|
break;
|
|
|
|
#endif /* WRITE_PROTECTION */
|
|
#endif /* FL_READ_ONLY */
|
|
#endif /* ABS_READ_WRITE */
|
|
|
|
#ifdef VERIFY_VOLUME
|
|
case FL_VERIFY_VOLUME :
|
|
if ((vol.tl.checkVolume != NULL) &&
|
|
(ioreq->irData == NULL) &&
|
|
(ioreq->irLength == 0 ) )
|
|
{
|
|
status = vol.tl.checkVolume(vol.tl.rec);
|
|
}
|
|
else
|
|
{
|
|
status = flFeatureNotSupported;
|
|
}
|
|
break;
|
|
#endif /* VERIFY_VOLUME */
|
|
|
|
#ifdef FL_LOW_LEVEL
|
|
case FL_GET_PHYSICAL_INFO:
|
|
status = getPhysicalInfo(&vol, ioreq);
|
|
break;
|
|
|
|
#ifndef NO_PHYSICAL_IO
|
|
case FL_PHYSICAL_READ:
|
|
status = physicalRead(&vol, ioreq);
|
|
break;
|
|
|
|
#ifndef FL_READ_ONLY
|
|
case FL_PHYSICAL_WRITE:
|
|
status = physicalWrite(&vol, ioreq);
|
|
break;
|
|
|
|
case FL_PHYSICAL_ERASE:
|
|
status = physicalErase(&vol, ioreq);
|
|
break;
|
|
#endif /* FL_READ_ONLY */
|
|
#endif /* NO_PHYSICAL_IO */
|
|
|
|
/* direct calls to the MTD */
|
|
#ifdef HW_OTP
|
|
case FL_OTP_SIZE:
|
|
if (vol.flash->otpSize != NULL)
|
|
{
|
|
word tmp = (word)ioreq->irFlags;
|
|
status = vol.flash->otpSize(vol.flash, (dword FAR2 *)(&ioreq->irCount ),
|
|
(dword FAR2 *)(&ioreq->irLength),
|
|
&tmp);
|
|
ioreq->irFlags = (unsigned)tmp;
|
|
}
|
|
else
|
|
{
|
|
status = flFeatureNotSupported;
|
|
}
|
|
break;
|
|
|
|
case FL_OTP_READ:
|
|
if (vol.flash->readOTP != NULL)
|
|
{
|
|
status = vol.flash->readOTP(vol.flash, (word)ioreq->irCount,
|
|
ioreq->irData, (word)ioreq->irLength);
|
|
}
|
|
else
|
|
{
|
|
status = flFeatureNotSupported;
|
|
}
|
|
break;
|
|
|
|
#ifndef FL_READ_ONLY
|
|
case FL_OTP_WRITE:
|
|
if (vol.flash->writeOTP != NULL)
|
|
{
|
|
status = vol.flash->writeOTP(vol.flash,ioreq->irData,
|
|
(word)ioreq->irLength);
|
|
}
|
|
else
|
|
{
|
|
status = flFeatureNotSupported;
|
|
}
|
|
break;
|
|
|
|
#endif /* FL_READ_ONLY */
|
|
|
|
case FL_UNIQUE_ID:
|
|
if (vol.flash->getUniqueId !=NULL)
|
|
{
|
|
status = vol.flash->getUniqueId(vol.flash, ioreq->irData);
|
|
}
|
|
else
|
|
{
|
|
status = flFeatureNotSupported;
|
|
}
|
|
break;
|
|
|
|
case FL_CUSTOMER_ID:
|
|
if (vol.flash->getUniqueId !=NULL)
|
|
{
|
|
byte buf[UNIQUE_ID_LEN];
|
|
status = vol.flash->getUniqueId (vol.flash, buf);
|
|
tffscpy (ioreq->irData,buf,CUSTOMER_ID_LEN);
|
|
}
|
|
else
|
|
{
|
|
status = flFeatureNotSupported;
|
|
}
|
|
break;
|
|
#endif /* HW_OTP */
|
|
|
|
#ifndef NO_IPL_CODE
|
|
#ifndef FL_READ_ONLY
|
|
case FL_WRITE_IPL:
|
|
status = writeIPL(vol.flash,(byte FAR1*)ioreq->irData,ioreq->irLength,ioreq->irFlags);
|
|
break;
|
|
#endif /* FL_READ_ONLY */
|
|
case FL_READ_IPL:
|
|
status = readIPL(vol.flash,(byte FAR1*)ioreq->irData,ioreq->irLength);
|
|
break;
|
|
#endif /* NO_IPL_CODE */
|
|
|
|
case FL_DEEP_POWER_DOWN_MODE:
|
|
if (vol.flash->enterDeepPowerDownMode !=NULL)
|
|
{
|
|
vol.flash->enterDeepPowerDownMode(vol.flash,(word)ioreq->irFlags);
|
|
status = flOK;
|
|
}
|
|
else
|
|
{
|
|
status = flFeatureNotSupported;
|
|
}
|
|
break;
|
|
|
|
#ifndef NO_INQUIRE_CAPABILITIES
|
|
case FL_INQUIRE_CAPABILITIES:
|
|
inquireCapabilities(vol.flash,(FLCapability FAR2 *)&(ioreq->irLength));
|
|
break;
|
|
#endif /* NO_INQUIRE_CAPABILITIES */
|
|
|
|
#endif /* FL_LOW_LEVEL */
|
|
|
|
case FL_VOLUME_INFO:
|
|
status = volumeInfo(&vol, ioreq);
|
|
break;
|
|
|
|
/* Pre mount routines */
|
|
#if (defined(FORMAT_VOLUME) && !defined(FL_READ_ONLY))
|
|
case FL_WRITE_BBT:
|
|
#ifndef NT5PORT
|
|
checkStatus(dismountPhysicalDrive(socket));
|
|
#else /*NT5PORT*/
|
|
status = dismountPhysicalDrive(socket);
|
|
if (status != flOK)
|
|
goto flCallExit;
|
|
#endif /*NT5PORT*/
|
|
#endif
|
|
case FL_COUNT_VOLUMES:
|
|
#ifdef QUICK_MOUNT_FEATURE
|
|
case FL_CLEAR_QUICK_MOUNT_INFO:
|
|
#endif /* QUICK_MOUNT_FEATURE */
|
|
#ifdef HW_PROTECTION
|
|
case FL_PROTECTION_GET_TYPE:
|
|
case FL_PROTECTION_REMOVE_KEY:
|
|
case FL_PROTECTION_INSERT_KEY:
|
|
#ifndef FL_READ_ONLY
|
|
case FL_PROTECTION_SET_LOCK:
|
|
case FL_PROTECTION_CHANGE_KEY:
|
|
case FL_PROTECTION_CHANGE_TYPE:
|
|
#endif /* FL_READ_ONLY */
|
|
#endif /* HW_PROTECTION */
|
|
status = flPreMount(functionNo , ioreq , vol.flash);
|
|
break;
|
|
default:
|
|
status = flBadFunction;
|
|
}
|
|
|
|
#if ((defined(FILES)) && (FILES > 0) && (!defined(FL_READ_ONLY)))
|
|
if (vol.volBuffer.checkPoint)
|
|
{
|
|
FLStatus st = flushBuffer(&vol);
|
|
if (status == flOK)
|
|
status = st;
|
|
}
|
|
#endif
|
|
|
|
/*********************************************/
|
|
/* Exit nicely - Release mutex of the socket */
|
|
/*********************************************/
|
|
|
|
flCallExit:
|
|
if(status==flOK)
|
|
status = setBusy(&vol,FL_OFF,curPartitionForEnvVars);
|
|
else
|
|
setBusy(&vol,FL_OFF,curPartitionForEnvVars); /* We're leaving */
|
|
|
|
return status;
|
|
}
|
|
|
|
#if POLLING_INTERVAL != 0
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* s o c k e t I n t e r v a l R o u t i n e */
|
|
/* */
|
|
/* Routine called by the interval timer to perform periodic socket */
|
|
/* actions and handle the watch-dog timer. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* None */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
/* Routine called at time intervals to poll sockets */
|
|
static void socketIntervalRoutine(void)
|
|
{
|
|
unsigned volNo;
|
|
Volume vol = vols;
|
|
|
|
flMsecCounter += POLLING_INTERVAL;
|
|
|
|
for (volNo = 0; volNo < noOfSockets; volNo++, pVol++)
|
|
if (flTakeMutex(&flMutex[volNo])) {
|
|
#ifdef FL_BACKGROUND
|
|
if (vol.flags & VOLUME_ABS_MOUNTED)
|
|
/* Allow background operation to proceed */
|
|
vol.tl.tlSetBusy(vol.tl.rec,FL_OFF);
|
|
#endif
|
|
flIntervalRoutine(vol.socket);
|
|
flFreeMutex(&flMutex[volNo]);
|
|
}
|
|
}
|
|
|
|
#endif /* POLLING_INTERVAL != 0 */
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l I n i t */
|
|
/* */
|
|
/* Initializes the FLite system, sockets and timers. */
|
|
/* */
|
|
/* Calling this function is optional. If it is not called, */
|
|
/* initialization will be done automatically on the first FLite call. */
|
|
/* This function is provided for those applications who want to */
|
|
/* explicitly initialize the system and get an initialization status. */
|
|
/* */
|
|
/* Calling flInit after initialization was done has no effect. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* None */
|
|
/* */
|
|
/* Returns: */
|
|
/* FLStatus : 0 on success, otherwise failed */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
FLStatus flInit(void)
|
|
{
|
|
if (!initDone) {
|
|
FLStatus status;
|
|
unsigned volNo;
|
|
Volume vol = vols;
|
|
IOreq req;
|
|
#ifdef LOG_FILE
|
|
FILE *out;
|
|
|
|
out=FL_FOPEN("EDCerr.txt","w");
|
|
FL_FPRINTF(out,"EDC error LOG\n");
|
|
FL_FCLOSE(out);
|
|
#endif /* LOG_FILE */
|
|
|
|
flInitGlobalVars();
|
|
|
|
#ifdef ENVIRONMENT_VARS
|
|
|
|
/* Call users initialization routine for :
|
|
* flUse8Bit,flUseNFTLCache,flUseisRAM
|
|
*/
|
|
flSetEnvVar();
|
|
|
|
if(flUse8Bit==1)
|
|
{
|
|
tffscpy = flmemcpy;
|
|
tffscmp = flmemcmp;
|
|
tffsset = flmemset;
|
|
}
|
|
else
|
|
{
|
|
tffscpy = flcpy;
|
|
tffsset = flset;
|
|
tffscmp = flcmp;
|
|
}
|
|
|
|
#endif /* ENVIRONMENT_VARS */
|
|
|
|
/*
|
|
* 1) Mark all the volumes as not used and free to be allocated.
|
|
* 2) Clear passowrd in order to make it invald.
|
|
*/
|
|
|
|
tffsset(vols,0,sizeof(vols));
|
|
|
|
for (volNo = 0,pVol = vols; volNo < VOLUMES; volNo++,pVol++)
|
|
{
|
|
/* The actual number of sockets is not yet known and will be retreaved by
|
|
* flRegisterComponents routine by the socket componenets. For now supply
|
|
* each of the possible sockets with its buffer and socket number.
|
|
*/
|
|
if ( volNo < SOCKETS)
|
|
{
|
|
vol.socket = flSocketOf(volNo);
|
|
vol.flash = flFlashOf(volNo);
|
|
tffsset(vol.socket,0,sizeof(FLSocket));
|
|
tffsset(vol.flash,0,sizeof(FLFlash));
|
|
vol.socket->volNo = volNo;
|
|
#ifdef WRITE_EXB_IMAGE
|
|
vol.moduleNo = INVALID_MODULE_NO; /* Ready for exb write operation */
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
vol.flash = NULL;
|
|
}
|
|
vol.volExecInProgress = NULL;
|
|
}
|
|
|
|
#if FILES > 0
|
|
initFS();
|
|
#endif
|
|
|
|
flSysfunInit();
|
|
|
|
#ifdef FL_BACKGROUND
|
|
flCreateBackground();
|
|
#endif
|
|
/* Initialize variales */
|
|
for (noOfTLs = 0 ;noOfTLs < TLS;noOfTLs++)
|
|
{
|
|
tlTable[noOfTLs].mountRoutine = NULL;
|
|
tlTable[noOfTLs].preMountRoutine = NULL;
|
|
tlTable[noOfTLs].formatRoutine = NULL;
|
|
}
|
|
initDone = TRUE;
|
|
noOfTLs = 0;
|
|
noOfDrives = 0;
|
|
noOfSockets = 0;
|
|
noOfMTDs = 0;
|
|
|
|
checkStatus(flRegisterComponents());
|
|
|
|
#ifdef COMPRESSION
|
|
checkStatus(flRegisterZIP());
|
|
#endif
|
|
|
|
#ifdef MULTI_DOC
|
|
#ifdef ENVIRONMENT_VARS
|
|
if(flUseMultiDoc==FL_ON)
|
|
{
|
|
checkStatus(flRegisterMTL());
|
|
}
|
|
#else
|
|
checkStatus(flRegisterMTL());
|
|
#endif /* ENVIRONMENT_VARS */
|
|
#endif /* MULT_DOC */
|
|
|
|
#ifdef BDK_ACCESS
|
|
bdkInit();
|
|
#endif
|
|
|
|
checkStatus(flInitSockets());
|
|
|
|
#if POLLING_INTERVAL > 0
|
|
checkStatus(flInstallTimer(socketIntervalRoutine,POLLING_INTERVAL));
|
|
#endif
|
|
|
|
/*
|
|
* Now that the number of actual sockets is known, create a mutex for
|
|
* each of the systems sockets. Multi-doc uses only 1 mutex.
|
|
*/
|
|
|
|
#ifdef MULTI_DOC
|
|
if ((noOfSockets)
|
|
#ifdef ENVIRONMENT_VARS
|
|
&&(flUseMultiDoc == FL_ON)
|
|
#endif /* ENVIRONMENT_VARS */
|
|
)
|
|
{ /* All sockets use the same mutex */
|
|
|
|
if (flCreateMutex(&flMutex[0]) != flOK)
|
|
return flGeneralFailure;
|
|
|
|
for (volNo = 0; volNo < noOfSockets ; volNo++)
|
|
{
|
|
vols[volNo].volExecInProgress = &flMutex[0];
|
|
}
|
|
}
|
|
else
|
|
#endif /* MULTI_DOC */
|
|
{ /* Each socket uses a diffren mutex */
|
|
|
|
for (volNo = 0; volNo < noOfSockets ; volNo++)
|
|
{
|
|
if (flCreateMutex(&flMutex[volNo]) != flOK)
|
|
return flGeneralFailure;
|
|
vols[volNo].volExecInProgress = &flMutex[volNo];
|
|
}
|
|
}
|
|
|
|
/* Count the number of volumes on all the systems sockets and
|
|
* initialize conversion table. The table is used to convert a socket
|
|
* and a partition numbers to the correct volume index in the vols record.
|
|
* Partition 0 of each of the sockets will recieve the volume record
|
|
* indexed with the socket number in the vols array. The rest of the
|
|
* volumes will be serialy allocated. New volume records can be allocated
|
|
* By the format routine. The format and the write BBT routines clear all
|
|
* volume records taken by the sockets except for the first.
|
|
*
|
|
* The partition and socket are passed to the TL module using 2 dedicated
|
|
* fields in the TL record. Both those values are also initiaized.
|
|
* All volumes on a specific socket will share the same mutex.
|
|
*/
|
|
|
|
tffsset(handleConversionTable,INVALID_VOLUME_NUMBER, /* Clear table */
|
|
sizeof(handleConversionTable));
|
|
|
|
for (pVol = vols , noOfDrives = (unsigned)noOfSockets , req.irHandle = 0;
|
|
req.irHandle < noOfSockets; req.irHandle++, pVol++)
|
|
{
|
|
/* Initialize partition 0 */
|
|
|
|
handleConversionTable[req.irHandle][0] = (byte)req.irHandle;
|
|
vol.tl.socketNo = (byte)req.irHandle;
|
|
vol.tl.partitionNo = 0;
|
|
vol.flags = VOLUME_ACCUPIED;
|
|
|
|
/* The rest of the partitions are initialzed only if multi-doc
|
|
* is not active since Multi-doc supports only the first volume
|
|
* of each socket.
|
|
*/
|
|
|
|
status = flPreMount(FL_COUNT_VOLUMES , &req , vol.flash);
|
|
if (status == flOK)
|
|
{
|
|
vol.volExecInProgress = &flMutex[req.irHandle];
|
|
for(volNo = 1;(volNo < req.irFlags) && (noOfDrives < VOLUMES); volNo++,noOfDrives++)
|
|
{
|
|
handleConversionTable[req.irHandle][volNo] = (byte)noOfDrives;
|
|
vols[noOfDrives].socket = vol.socket;
|
|
vols[noOfDrives].flash = vol.flash;
|
|
vols[noOfDrives].tl.socketNo = (byte)req.irHandle;
|
|
vols[noOfDrives].tl.partitionNo = (byte)volNo;
|
|
vols[noOfDrives].volExecInProgress =
|
|
vol.volExecInProgress;
|
|
vol.flags = VOLUME_ACCUPIED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return flOK;
|
|
}
|
|
|
|
#ifdef EXIT
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* f l E x i t */
|
|
/* */
|
|
/* If the application ever exits, flExit should be called before exit. */
|
|
/* flExit flushes all buffers, closes all open files, powers down the */
|
|
/* sockets and removes the interval timer. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* None */
|
|
/* */
|
|
/* Returns: */
|
|
/* Nothing */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void NAMING_CONVENTION flExit(void)
|
|
{
|
|
unsigned volNo;
|
|
Volume vol = vols;
|
|
FLBoolean mutexTaken = FALSE;
|
|
|
|
if(flInit==FALSE)
|
|
return;
|
|
|
|
/* Dismount the TL and MTD */
|
|
|
|
for (volNo = 0; (volNo < VOLUMES); volNo++,pVol++)
|
|
{
|
|
if ((vol.flags & VOLUME_ACCUPIED) && (setBusy(&vol,FL_ON,vol.tl.partitionNo) == flOK))
|
|
{
|
|
dismountVolume(&vol);
|
|
|
|
#ifdef FL_LOW_LEVEL
|
|
dismountLowLevel(&vol);
|
|
#endif
|
|
setBusy(&vol,FL_OFF,vol.tl.partitionNo);
|
|
}
|
|
}
|
|
|
|
/* Dismount SOCKET */
|
|
|
|
pVol = vols;
|
|
for (volNo = 0; volNo < noOfSockets ; volNo++,pVol++)
|
|
{
|
|
#ifdef MULTI_DOC
|
|
#ifdef ENVIRONMENT_VARS
|
|
if (flUseMultiDoc == FL_ON) /* multi-doc not active */
|
|
#endif /* ENVIRONMENT_VARS */
|
|
if (volNo == 0)
|
|
#endif /* MULTI_DOC */
|
|
mutexTaken = (setBusy(&vol,FL_ON,vol.tl.partitionNo) == flOK) ? TRUE:FALSE;
|
|
|
|
if (mutexTaken == TRUE)
|
|
{
|
|
flFreeMutex(execInProgress); /* free the mutex that was taken in setBusy(FL_ON) */
|
|
/* delete mutex protecting FLite volume access */
|
|
flDeleteMutex(execInProgress);
|
|
mutexTaken = FALSE;
|
|
}
|
|
flExitSocket(vol.socket);
|
|
}
|
|
|
|
#if POLLING_INTERVAL != 0
|
|
flRemoveTimer();
|
|
#endif
|
|
|
|
#ifdef ALLOCTST
|
|
out_data_sz();
|
|
#endif
|
|
initDone = FALSE;
|
|
initGlobalVarsDone = FALSE;
|
|
pVol = NULL;
|
|
}
|
|
|
|
#ifdef __BORLANDC__
|
|
#ifdef EXIT
|
|
#pragma exit flExit
|
|
#endif /* EXIT */
|
|
#include <dos.h>
|
|
|
|
static int cdecl flBreakExit(void)
|
|
{
|
|
flExit();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void setCBreak(void)
|
|
{
|
|
ctrlbrk(flBreakExit);
|
|
}
|
|
|
|
#pragma startup setCBreak
|
|
|
|
#endif
|
|
|
|
#endif
|