windows-nt/Source/XPSP1/NT/drivers/storage/tffsport/flmtl.c
2020-09-26 16:20:57 +08:00

1828 lines
70 KiB
C

/***********************************************************************************/
/* 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 */
/***********************************************************************************/
/*
* $Log: V:/Flite/archives/TrueFFS5/Src/flmtl.c_V $
*
* Rev 1.11 Nov 08 2001 10:49:20 oris
* Added support for up to 1GB DiskOnChips.
*
* Rev 1.10 Sep 24 2001 18:23:40 oris
* Removed warnings.
*
* Rev 1.9 Sep 15 2001 23:46:16 oris
* Changed progress callback routine to support up to 64K units.
*
* Rev 1.8 Jul 13 2001 01:05:16 oris
* Removed warnings.
* Bug fix - exception when format routine is called with null progress call back routine.
* Report noOfDrives as 1.
*
* Rev 1.7 Jun 17 2001 08:18:40 oris
* Add improoved the format progress call back routine.
* Removed fack number of TLS in mtlPreMount routine.
*
* Rev 1.6 May 21 2001 16:13:08 oris
* Replaced memcpy with tffscpy Macro.
*
* Rev 1.5 May 17 2001 18:54:26 oris
* Removed warnings.
*
* Rev 1.4 May 16 2001 21:19:02 oris
* Changed the fl_MTLdefragMode variable to a global environment variable.
* MTL now changes the noOfDriver variable after the first mount and restores it after uninstall.
* Added missing ifdef directives.
* Removed warnings.
* Removed readBBT and writeBBT routines.
* Improved MTL protection routine.
*
* Rev 1.3 Apr 01 2001 08:01:18 oris
* copywrite notice.
* Alligned left all # directives.
*
* Rev 1.2 Feb 18 2001 12:06:54 oris
* Install mtl will now fake the noOfTLs in order to be the only TL.
* Placed mtlFormat under FORMAT_VOLUME compilation flag.
* Place mtlProtection under HW_PROTECTION compilation flag.
* Changed mtlPreMount arg sanity check to include partition number.
* Changed tmpflash to tmpFlash.
*
* Rev 1.1 Feb 14 2001 02:09:38 oris
* Changed readBBT to return media size.
* Added boundry argument to writeBBT.
*
* Rev 1.0 Feb 12 2001 12:07:02 oris
* Initial revision.
*
* Rev 1.3 Jan 24 2001 18:10:48 oris
* Bug fix: MTL failed to register because noOfTLs wan't updated
*
* Rev 1.2 Jan 24 2001 16:34:06 oris
* MTL defragmentation changed, alt. defragmentation added.
*
* Rev 1.1 Jan 22 2001 22:10:50 amirm
* #define FL_MTL_HIDDEN_SECTORS added
*
* Rev 1.0 Jan 22 2001 18:27:54 amirm
* Initial revision.
*
*/
/*
* Include
*/
#include "fltl.h"
/*
* Configuration
*/
/* This defined sets the number of sectors to ignore starting from the
* first device. The default value should be 1 therfore ignoring sector
* 0 of the first device. Ignioring sector 0 gurentees that the combined
* device does not use the BPB of the first device, which does not report
* the C/H/S of the new combined media. The next format operation would
* write a new BPB that would fit the new combined media size.
*/
#define FL_MTL_HIDDEN_SECTORS 1
/*
* Extern
*/
/*
* Globals
*/
FLStatus flRegisterMTL (void); /* see also stdcomp.h */
FLStatus flmtlInstall (void);
FLStatus flmtlUninstall (void);
/*
* Local types
*/
/* I/O vector for splitting I/O among physical devices */
typedef struct {
SectorNo startSector;
SectorNo sectors;
} tMTLiov;
/* Physical flash device. Part of MTL volume. */
typedef struct {
SectorNo virtualSectors;
TL tl;
dword physicalSize;
} tMTLPhysDev;
/* MTL volume */
struct tTLrec {
int noOfTLs;
int noOfDrives;
SectorNo virtualSectors;
tMTLPhysDev devs[SOCKETS];
};
typedef TLrec MTL;
/*
* Local data
*/
/* only one MTL volume is supported */
static MTL mvol;
/* progress callBack routine */
FLProgressCallback globalProgressCallback = NULL;
/* access macros for MTL volume */
#define mT(dev) (mvol.devs[dev].tl)
#define mS(dev) (mvol.devs[dev].virtualSectors)
#define mP(dev) (mvol.devs[dev].physicalSize)
#define mpT(pvol,dev) ((pvol)->devs[dev].tl)
#define mpF(pvol,dev) ((pvol)->devs[dev].flash)
#define mpS(pvol,dev) ((pvol)->devs[dev].virtualSectors)
/*
* Local routines
*/
static FLStatus mtlSplitIO (MTL *pvol, SectorNo startSector,
SectorNo sectors, tMTLiov *iov);
static FLStatus mtlWrite (MTL *pvol, SectorNo startSector,
SectorNo *pSectorsToWrite, void FAR1 *buf);
static FLStatus mtlMount (unsigned volNo, TL *tl, FLFlash *flash,
FLFlash **notUsed);
#if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)
static FLStatus mtlDefragment (MTL *pvol, long FAR2 *sectorsNeeded);
#ifdef ENVIRONMENT_VARS
static FLStatus mtlDefragmentAlt (MTL *pvol, long FAR2 *sectorsNeeded);
#endif /* ENVIRNOMETN_VARS */
#endif /* DEFRAGMENT_VOLUME || SINGLE_BUFFER */
static void mtlUnmount (MTL *pvol);
#ifdef FORMAT_VOLUME
static FLStatus mtlFormat (unsigned volNo, TLFormatParams* formatParams,
FLFlash *flash);
#endif /* FORMAT_VOLUME */
static FLStatus mtlWriteSector (MTL *pvol, SectorNo sectorNo,
void FAR1 *fromAddress);
static FLStatus mtlDeleteSector (MTL *pvol, SectorNo sectorNo,
SectorNo noOfSectors);
static FLStatus mtlInfo (MTL *pvol, TLInfo *tlInfo);
static FLStatus mtlSetBusy (MTL *pvol, FLBoolean state);
static SectorNo mtlSectorsInVolume (MTL *pvol);
static const void FAR0 *mtlMapSector (MTL *pvol, SectorNo sectorNo,
CardAddress *physAddress);
#ifdef HW_PROTECTION
static FLStatus mtlProtection(FLFunctionNo callType,
IOreq FAR2* ioreq, FLFlash* flash);
#endif /* HW_PROTECTION */
static FLStatus mtlPreMount(FLFunctionNo callType, IOreq FAR2* ioreq ,
FLFlash* flash,FLStatus* status);
/* -------------------------------------------------------------------------- *
* *
* m t l S p l i t I O *
* *
* Setup I/O vector for splitting I/O request among physical devices. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* startSector : starting sector # (zero-based) *
* sectors : total number of sectors *
* iov : I/O vector to setup *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlSplitIO (MTL *pvol, SectorNo startSector, SectorNo sectors,
tMTLiov *iov)
{
SectorNo devFirstSectNo;
SectorNo devLastSectNo;
int iDev;
/* check 'pvol' for sanity */
if (pvol != &mvol)
return flBadDriveHandle;
/* clear I/O vector */
for (iDev = 0; iDev < SOCKETS; iDev++) {
iov[iDev].sectors = (SectorNo) 0;
iov[iDev].startSector = (SectorNo)(-1);
}
/* split I/O operation among physical devices */
devFirstSectNo = (SectorNo) 0;
for (iDev = 0; (iDev < noOfSockets) && (sectors > ((SectorNo) 0)); iDev++) {
devLastSectNo = devFirstSectNo + (mpS(pvol,iDev) - ((SectorNo) 1));
if ((startSector >= devFirstSectNo) && (startSector <= devLastSectNo)) {
iov[iDev].startSector = startSector - devFirstSectNo + FL_MTL_HIDDEN_SECTORS;
iov[iDev].sectors = devLastSectNo - startSector + ((SectorNo) 1);
startSector = devLastSectNo + ((SectorNo) 1);
if (sectors <= iov[iDev].sectors) {
iov[iDev].sectors = sectors;
startSector = (SectorNo) 0;
sectors = (SectorNo) 0;
}
else {
sectors -= iov[iDev].sectors;
}
}
devFirstSectNo = devLastSectNo + ((SectorNo) 1);
}
if (sectors > ((SectorNo) 0)) {
DEBUG_PRINT(("Debug: can't split I/O request among physical devices.\n"));
return flNoSpaceInVolume;
}
return flOK;
}
/* -------------------------------------------------------------------------- *
* *
* m t l M a p S e c t o r *
* *
* TL's standard 'map one sector' routine. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* sectorNo : sector # to map (zero-based) *
* physAddress : optional pointer to receive sector's physical *
* address on the media *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static const void FAR0 *mtlMapSector (MTL *pvol, SectorNo sectorNo,
CardAddress *physAddress)
{
SectorNo sectorsToMap;
tMTLiov iov[SOCKETS];
int iDev;
/* pass call to the TL of the respective underlaying physical device */
sectorsToMap = (SectorNo) 1;
if (mtlSplitIO(pvol, sectorNo, sectorsToMap, iov) != flOK)
return NULL;
for (iDev = 0; iDev < noOfSockets; iDev++) {
if (iov[iDev].sectors != ((SectorNo) 0)) {
return mpT(pvol,iDev).mapSector (mpT(pvol,iDev).rec,
iov[iDev].startSector, physAddress);
}
}
return NULL;
}
/* -------------------------------------------------------------------------- *
* *
* m t l W r i t e *
* *
* Split call to write multiple consequitive sectors among TLs of the *
* underlaying physical devices. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* startSector : starting sector # (zero-based) *
* pSectorsToWrite : on entry - total number of sectors to write *
* on exit - total number of sectors written *
* buf : buffer containing data to write to the media *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlWrite (MTL *pvol, SectorNo startSector,
SectorNo *pSectorsToWrite, void FAR1 *buf)
{
tMTLiov iov[SOCKETS];
int iDev;
/* split call among TLs of the underlaying physical devices */
checkStatus( mtlSplitIO(pvol, startSector, *pSectorsToWrite, iov) );
for (iDev = 0; iDev < noOfSockets; iDev++) {
if (iov[iDev].sectors != ((SectorNo) 0)) {
checkStatus( mpT(pvol,iDev).writeSector(mpT(pvol,iDev).rec,
iov[iDev].startSector,buf) );
*pSectorsToWrite -= iov[iDev].sectors;
buf = BYTE_ADD_FAR(buf,(CardAddress)iov[iDev].sectors << SECTOR_SIZE_BITS);
}
}
if (*pSectorsToWrite != ((SectorNo) 0))
return flIncomplete;
return flOK;
}
/* -------------------------------------------------------------------------- *
* *
* m t l W r i t e S e c t o r *
* *
* TL's standard 'write one sector' routine. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* sectorNo : sector # to write to (zero-based) *
* fromAddress : buffer containing data to write to the media *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlWriteSector (MTL *pvol, SectorNo sectorNo, void FAR1 *fromAddress)
{
SectorNo sectorsToWrite = (SectorNo) 1;
/* pass call to the TL of the respective underlaying physical device */
checkStatus( mtlWrite(pvol, sectorNo, &sectorsToWrite, (char FAR1 *)fromAddress) );
if (sectorsToWrite != ((SectorNo) 0))
return flIncomplete;
return flOK;
}
/* -------------------------------------------------------------------------- *
* *
* m t l D e l e t e S e c t o r *
* *
* TL's standard 'delete range of sectors' routine. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* startSector : starting sector # (zero-based) *
* sectors : total number of sectors to delete *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlDeleteSector (MTL *pvol, SectorNo startSector,
SectorNo sectors)
{
tMTLiov iov[SOCKETS];
int iDev;
/* split call among TLs of the underlaying physical devices */
checkStatus( mtlSplitIO(pvol, startSector, sectors, iov) );
for (iDev = 0; iDev < noOfSockets; iDev++) {
if (iov[iDev].sectors != ((SectorNo) 0)) {
checkStatus( mpT(pvol,iDev).deleteSector(mpT(pvol,iDev).rec,
iov[iDev].startSector,
iov[iDev].sectors) );
}
sectors -= iov[iDev].sectors;
}
if (sectors != ((SectorNo) 0))
return flIncomplete;
return flOK;
}
/* -------------------------------------------------------------------------- *
* *
* m t l I n f o *
* *
* TL's standard 'get info' routine. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* pTLinfo : pointer to the TLInfo structure to fill in *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlInfo (MTL *pvol, TLInfo *pTLinfo)
{
TLInfo tmp;
int iDev;
/* check 'pvol' for sanity */
if (pvol != &mvol)
return flBadDriveHandle;
pTLinfo->sectorsInVolume = pvol->virtualSectors;
/*
* The 'eraseCycles' is reported as a sum of that of all the underlaying
* physical devices. The 'bootAreaSize' is set to the one of the 1st
* underlaying physical device.
*/
pTLinfo->bootAreaSize = (dword) 0;
pTLinfo->eraseCycles = (dword) 0;
for (iDev = 0; iDev < noOfSockets; iDev++) {
if (mpT(pvol,iDev).getTLInfo != NULL) {
checkStatus( mpT(pvol,iDev).getTLInfo(mpT(pvol,iDev).rec, &tmp) );
pTLinfo->eraseCycles += tmp.eraseCycles;
if (iDev == 0)
pTLinfo->bootAreaSize = tmp.bootAreaSize;
}
}
return flOK;
}
/* -------------------------------------------------------------------------- *
* *
* m t l S e t B u s y *
* *
* TL's standard routine which is called at the beginning and and the end of *
* the block device operation. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* state : FL_ON - start of block device operation *
* FL_OFF - end of block device operation *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlSetBusy (MTL *pvol, FLBoolean state)
{
int iDev;
/* check 'pvol' for sanity */
if (pvol != &mvol)
return flBadDriveHandle;
/* broadcast this call to TLs of all the underlaying physical devices */
for (iDev = 0; iDev < noOfSockets; iDev++) {
if (mpT(pvol,iDev).tlSetBusy != NULL) {
checkStatus( mpT(pvol,iDev).tlSetBusy(mpT(pvol,iDev).rec, state) );
}
}
return flOK;
}
/* -------------------------------------------------------------------------- *
* *
* m t l S e c t o r s I n V o l u m e *
* *
* Report the total number of sectors in the volume. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* *
* Returns : *
* *
* Total number of sectors in the volume, or zero in case of error. *
* *
* -------------------------------------------------------------------------- */
static SectorNo mtlSectorsInVolume (MTL *pvol)
{
/* check 'pvol' for sanity */
if (pvol != &mvol)
return ((SectorNo) 0);
return pvol->virtualSectors;
}
#if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)
/* -------------------------------------------------------------------------- *
* *
* m t l D e f r a g m e n t *
* *
* TL's standard garbage collection / volume defragmentaion routine. *
* *
* Note : The garbage collection algorithm will try and free the required *
* number of sectors on each of the combined devices. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* sectorsNeeded : On entry - minimum number of free sectors that *
* are requested to be on the media upon call *
* completion. Two special cases: zero for *
* complete defragmentation of all the physical *
* devices, and '-1' for minimal defragmentation *
* of each physical device. *
* On exit - actual number of free sectors on *
* the media. *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlDefragment (MTL *pvol, long FAR2 *sectorsNeeded)
{
long freeSectors;
FLStatus status;
int iDev;
long tmp;
FLStatus tmpStatus;
/* check args for sanity */
if (pvol != &mvol)
return flBadDriveHandle;
/*
* Pass call to the TL of the respective underlaying physical device.
* Count total number of free sectors on all devices.
*/
status = flOK;
freeSectors = (long) 0;
for (iDev = 0; iDev < noOfSockets; iDev++) {
if (mpT(pvol,iDev).defragment != NULL) {
switch (*sectorsNeeded) {
case ((long)(-1)): /* minimal defragmenation */
tmp = (long)(-1);
break;
case ((long) 0): /* complete defragmenation */
tmp = mpS(pvol,iDev);
break;
default: /* partial defragmentation */
if (*sectorsNeeded < (long) mpS(pvol,iDev))
{
tmp = *sectorsNeeded;
}
else
{
tmp = mpS(pvol,iDev); /* complete defragmentation */
}
break;
}
tmpStatus = mpT(pvol,iDev).defragment (mpT(pvol,iDev).rec, ((long FAR2 *) &tmp));
if (tmpStatus != flBadFormat)
{
freeSectors += tmp;
}
else
{
status = tmpStatus;
}
}
}
*sectorsNeeded = freeSectors;
if (*sectorsNeeded == ((long) 0))
return flNoSpaceInVolume;
return status;
}
#ifdef ENVIRONMENT_VARS
/* -------------------------------------------------------------------------- *
* *
* m t l D e f r a g m e n t A l t *
* *
* TL's alternative garbage collection / volume defragmentaion routine. *
* *
* Note : The garbage collection algorithm Perform quick gurbage collections *
* from drive 0 until there is no more "garbage" to collect or until *
* there is enough clean space. If the specified clean spage was not *
* achieved try the next device. *
* While this method is faster then the standard defragment, it does *
* not gurantee that when the clean sectors are needed they will be *
* available. This is becuase write operation on MTL will directed *
* the write operation to a specific device according to the specifed *
* virtual sector number (not necceseraly starting from device #0). *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* sectorsNeeded : On entry - minimum number of free sectors that *
* are requested to be on the media upon call *
* completion. Two special cases: zero for *
* complete defragmentation of all the physical *
* devices, and '-1' for minimal defragmentation *
* of each physical device. *
* On exit - actual number of free sectors on *
* the media. *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlDefragmentAlt (MTL *pvol, long FAR2 *sectorsNeeded)
{
long freeSectors;
FLBoolean keepWorking;
FLBoolean driveDone[SOCKETS];
long freeSectorsOnDrive[SOCKETS];
FLStatus status;
int iDev;
FLStatus tmpStatus;
long tmp;
/* check args for sanity */
if (pvol != &mvol)
return flBadDriveHandle;
/*
* Pass call to the TL of the respective underlaying physical device.
* Count total number of free sectors on all devices.
*/
status = flOK;
freeSectors = (long) 0;
if ((*sectorsNeeded == ((long) -1)) || (*sectorsNeeded == (long)0)) {
/* Either total or minimal defragmentation of all physical devices. */
for (iDev = 0; iDev < noOfSockets; iDev++) {
if (mpT(pvol,iDev).defragment != NULL) {
if (*sectorsNeeded == ((long) -1))
tmp = (long)(-1); /* minimal defragmenation */
else
tmp = mpS(pvol,iDev); /* complete defragmenation */
tmpStatus = mpT(pvol,iDev).defragment (mpT(pvol,iDev).rec, ((long FAR2 *) &tmp));
if (tmpStatus != flBadFormat) {
freeSectors += tmp;
}
else {
DEBUG_PRINT(("Debug: Error defragmenting physical device.\n"));
status = tmpStatus;
}
}
}
}
else { /* Partial defragmentaion of the MTL volume */
for (iDev = 0; iDev < SOCKETS; iDev++) {
freeSectorsOnDrive[iDev] = (long) 0;
if ((iDev < noOfSockets) && (mpT(pvol,iDev).defragment != NULL))
driveDone[iDev] = FALSE;
else
driveDone[iDev] = TRUE;
}
keepWorking = TRUE;
while (keepWorking == TRUE) {
keepWorking = FALSE;
for (iDev = 0; iDev < noOfSockets; iDev++) {
/*
* Do minimal defragmentation of this physical device. If we
* have got error, or haven't gained any more free sectors,
* this physical device is done. If that is the case for all
* physical devices, the MTL defragmentation is done. If the
* required number of free sectors has been reached, MTL
* defragmentation is done.
*/
if (driveDone[iDev] != TRUE) {
tmp = (long) -1;
tmpStatus = mpT(pvol,iDev).defragment (mpT(pvol,iDev).rec, ((long FAR2 *) &tmp));
if (tmpStatus != flBadFormat) {
if (freeSectorsOnDrive[iDev] < tmp) {
/* got few more free sectors on that physical device */
keepWorking = TRUE;
freeSectors += (tmp - freeSectorsOnDrive[iDev]);
freeSectorsOnDrive[iDev] = tmp;
if (freeSectors >= *sectorsNeeded) {
/* required number of free sectors reached */
keepWorking = FALSE;
break;
}
}
else { /* didn't gain any free sectors */
driveDone[iDev] = TRUE;
}
}
else {
DEBUG_PRINT(("Debug: Error defragmenting physical device.\n"));
driveDone[iDev] = TRUE;
status = tmpStatus;
}
}
} /* for (iDev) */
} /* while (keepWorking */
}
*sectorsNeeded = freeSectors;
if (*sectorsNeeded == ((long) 0))
return flNoSpaceInVolume;
return status;
}
#endif /* ENVIRONEMENT_VARS */
#endif /* DEFRAGMENT_VOLUME || SINGLE_BUFFER */
#ifdef HW_PROTECTION
/* -------------------------------------------------------------------------- *
* *
* m t l P r o t e c t i o n *
* *
* TL's protection routine. *
* *
* Parameters : *
* *
* callType : pre mount protection operation type. *
* ioreq : pointer to the structure containing i\o fields *
* flash : pointer to the flash record of device #0
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlProtection(FLFunctionNo callType, IOreq FAR2* ioreq,
FLFlash* flash)
{
FLSocket *socket;
FLStatus status;
FLStatus callStatus;
FLFlash tmpFlash;
int iTL;
int iDev = 0;
unsigned flags = 0;
/*
* Do flash recognition and identify protection attributes for devices
* #0 .. (mvol.noOfSockets - 1) verifing that the operation can be
* preformed and that the protection attributes of all the devieces
* match.
*/
tffscpy(&tmpFlash,flash,sizeof (tmpFlash)); /* Use the given flash */
while(1)
{
/* The tmpFlash record is already intialized Try all the TLs */
status = flUnknownMedia;
for (iTL = 1;(iTL < mvol.noOfTLs) && (status == flUnknownMedia); iTL++)
{
if ((tlTable[iTL].formatRoutine == NULL) || /* TL filter */
(tlTable[iTL].preMountRoutine == NULL))
continue;
status = tlTable[iTL].preMountRoutine(FL_PROTECTION_GET_TYPE,
ioreq,&tmpFlash,&callStatus);
}
if (status != flOK)
{
DEBUG_PRINT(("Debug: no TL recognized the device, MTL protection aborted.\n"));
return flFeatureNotSupported;
}
if (callStatus != flOK)
{
return callStatus;
}
/* Check protection attributes */
if ((ioreq->irFlags & PROTECTABLE) == 0)
return flNotProtected;
if (iDev == 0) /* First device */
{
flags = ioreq->irFlags;
}
else
{
/* Diffrent protection attributes on diffrent devices */
if (ioreq->irFlags != flags)
return flMultiDocContrediction;
}
/* Validity check for the proper function call */
switch(callType)
{
case FL_PROTECTION_GET_TYPE: /* Identify protection */
if (iDev == noOfSockets-1)
return flOK;
break;
case FL_PROTECTION_SET_LOCK: /* Change protection */
case FL_PROTECTION_CHANGE_KEY:
case FL_PROTECTION_CHANGE_TYPE:
if (!(flags & CHANGEABLE_PROTECTION ) ||
(tmpFlash.protectionBoundries == NULL ) ||
(tmpFlash.protectionSet == NULL ))
{
return flUnchangeableProtection;
}
default: /* Insert and remove Key */
break;
}
/* Identify flash for next device */
if (iDev < noOfSockets - 1)
{
iDev++;
socket = flSocketOf (iDev);
/* Identify */
status = flIdentifyFlash (socket, &tmpFlash);
if ((status != flOK) && (status != flUnknownMedia))
{
DEBUG_PRINT(("Debug: no MTD recognized the device, MTL protection aborted.\n"));
return status;
}
}
else
break;
} /* for(iDev) */
/*
* Pass call to the TL of the respective underlaying physical device.
* Do flash recognition try all TLs registered in tlTable[]. Assume MTL
* is in tlTable[0], so skip it. Skip all the TL filters as well.
*/
for (iDev = 0, callStatus = flOK;
(iDev < noOfSockets) && (callStatus == flOK); iDev++)
{
socket = flSocketOf (iDev);
/* Identify */
status = flIdentifyFlash (socket, &tmpFlash);
if ((status != flOK) && (status != flUnknownMedia))
{
DEBUG_PRINT(("Debug: no MTD recognized the device, MTL protection aborted.\n"));
return status;
}
/* Try all the TLs */
status = flUnknownMedia;
for (iTL = 1; (iTL < mvol.noOfTLs) && (status == flUnknownMedia); iTL++)
{
if ((tlTable[iTL].formatRoutine == NULL) || /* TL filter */
(tlTable[iTL].preMountRoutine == NULL))
continue;
status = tlTable[iTL].preMountRoutine(callType,ioreq,
&tmpFlash,&callStatus);
}
if (status != flOK)
{
DEBUG_PRINT(("Debug: no TL recognized the device, MTL protection aborted.\n"));
return flFeatureNotSupported;
}
}
return callStatus;
}
#endif /* HW_PROTECTION */
/* -------------------------------------------------------------------------- *
* *
* m t l P r e M o u n t *
* *
* TL's standard volume pre mount routine. *
* *
* Parameters : *
* *
* callType : pre mount operation type. *
* ioreq : pointer to the structure containing i\o fields *
* flash : MTD attached to the 1st underlaying physical *
* device *
* *
* Returns : *
* *
* The routine always return flOK in order to stop other TLs from trying *
* to perform the operation. The true status code is returned in the *
* 'status' parameter. flOK on success, otherwise respective error code. * *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlPreMount(FLFunctionNo callType, IOreq FAR2* ioreq ,
FLFlash* flash,FLStatus* status)
{
/* arg sanity check */
if (ioreq->irHandle != 0)
{
DEBUG_PRINT(("Debug: can't execute, MTL must address first volume of socket 0.\n"));
*status = flBadParameter;
return flOK;
}
switch (callType)
{
case FL_COUNT_VOLUMES:
/* Count VOLUMES routine. We assume that while MTL is mounted only
* one device of each socket can be mounted.
*/
ioreq->irFlags = 1;
*status = flOK;
break;
/* Protection rouines. Call each of the underlaying physical devices. */
#ifdef HW_PROTECTION
case FL_PROTECTION_GET_TYPE:
case FL_PROTECTION_SET_LOCK:
case FL_PROTECTION_CHANGE_KEY:
case FL_PROTECTION_CHANGE_TYPE:
case FL_PROTECTION_REMOVE_KEY:
case FL_PROTECTION_INSERT_KEY:
*status = mtlProtection(callType,ioreq,flash);
break;
#endif /* HW_PROTECTION */
/* Write Bad Block Table. Call each of the underlaying physical device. */
case FL_WRITE_BBT:
*status = flFeatureNotSupported/*mtlWriteBBT(ioreq)*/;
return flFeatureNotSupported;
default:
return flBadParameter;
}
DEBUG_PRINT(("Debug: MTL premount succeeded.\n"));
return flOK;
}
/* -------------------------------------------------------------------------- *
* *
* m t l U n m o u n t *
* *
* TL's standard volume unmount routine. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* *
* Returns : *
* *
* none *
* *
* -------------------------------------------------------------------------- */
static void mtlUnmount (MTL *pvol)
{
int iDev;
/* check 'pvol' for sanity */
if (pvol != &mvol)
return;
/* broadcast this call to TLs of all the underlaying physical devices */
for (iDev = 0; iDev < noOfSockets; iDev++) {
if (mpT(pvol,iDev).dismount != NULL) {
mpT(pvol,iDev).dismount (mpT(pvol,iDev).rec);
}
}
/* Return the real number of drives */
noOfDrives = mvol.noOfDrives;
DEBUG_PRINT(("Debug: MTL dismounted succeeded.\n"));
}
/* -------------------------------------------------------------------------- *
* *
* m t l M o u n t *
* *
* TL's standard volume mount routine. *
* *
* Parameters : *
* *
* volNo : volume #, must be zero *
* tl : pointer to TL structure to fill in *
* flash : MTD attached to the 1st underlaying physical *
* device *
* forCallback : MTD for power on callback (not used). *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlMount (unsigned volNo, TL *tl, FLFlash *flash,
FLFlash **forCallback)
{
FLFlash tmpFlash;
FLFlash *volForCallback;
FLSocket *socket;
FLStatus status = flUnknownMedia;
int iTL;
int iDev = 0;
/* Arg sanity check */
if (volNo != ((unsigned) 0)) {
DEBUG_PRINT(("Debug: can't mount, MTL volume # is not zero.\n"));
return flBadParameter;
}
/*
* Do TL mount for device #0. Routine flIdentifyFlash() has already been
* called for this device (see arguement 'flash')
*/
volForCallback = NULL;
/* mT(0).recommendedClusterInfo = NULL;
mT(0).writeMultiSector = NULL;
mT(0).readSectors = NULL; */
/*
* Try all TLs registered in tlTable[]. Assume MTL is in tlTable[0], so
* skip it. Skip all the TL filters as well.
*/
for (iTL = 1; (iTL < mvol.noOfTLs) && (status != flOK); iTL++) {
if (tlTable[iTL].formatRoutine == NULL) /* TL filter */
continue;
status = tlTable[iTL].mountRoutine (0, &mT(0), flash, &volForCallback);
}
if (status != flOK) {
DEBUG_PRINT(("Debug: no TL recognized device #0, MTL mount aborted.\n"));
return status;
}
mP(iDev) = (dword)(flash->chipSize * flash->noOfChips); /* Physical size */
if (volForCallback)
volForCallback->setPowerOnCallback (volForCallback);
/*
* Do flash recognition and TL mount for devices #1 .. (mvol.noOfSockets - 1).
* First call flIdentifyFlash() to find MTD, then try all TLs registered
* in tlTable[]. Assume MTL is in tlTable[0], so skip it. Skip all the
* TL filters as well.
*/
for (iDev = 1; iDev < noOfSockets; iDev++) {
socket = flSocketOf (iDev);
status = flIdentifyFlash (socket, &tmpFlash);
if ((status != flOK) && (status != flUnknownMedia)) {
DEBUG_PRINT(("Debug: no MTD recognized the device, MTL mount aborted.\n"));
goto exitMount;
}
volForCallback = NULL;
mP(iDev) = (dword)(tmpFlash.chipSize * tmpFlash.noOfChips); /* Physical size */
mT(iDev).partitionNo = 0;
mT(iDev).socketNo = (byte)iDev;
/* mT(iDev).recommendedClusterInfo = NULL;
mT(iDev).writeMultiSector = NULL;
mT(iDev).readSectors = NULL;*/
status = flUnknownMedia;
for (iTL = 1; (iTL < mvol.noOfTLs) && (status != flOK); iTL++) {
if (tlTable[iTL].formatRoutine == NULL) /* TL filter */
continue;
status = tlTable[iTL].mountRoutine (iDev, &mT(iDev), &tmpFlash, &volForCallback);
}
if (status != flOK) {
DEBUG_PRINT(("Debug: no TL recognized the device, MTL mount aborted.\n"));
goto exitMount;
}
if (volForCallback)
volForCallback->setPowerOnCallback (volForCallback);
} /* for (iDev) */
/* Count the total of virtual sectors across all devices */
mvol.virtualSectors = (SectorNo) 0;
for (iDev = 0; iDev < SOCKETS; iDev++) {
mS(iDev) = (SectorNo) 0;
if (iDev >= noOfSockets)
continue;
mS(iDev) = mT(iDev).sectorsInVolume (mT(iDev).rec) - FL_MTL_HIDDEN_SECTORS;
mvol.virtualSectors += mS(iDev);
}
exitMount:
if (status != flOK)
{
/* If one of the devices failed mount dismount all devices */
for (;iDev >=0;iDev--)
{
if (mT(iDev).dismount != NULL)
mT(iDev).dismount(mT(iDev).rec);
}
DEBUG_PRINT(("Debug: MTL mount failed.\n"));
return status;
}
/*
* Attach MTL-specific record to 'tl'. This record will be passed
* as the first arguement to all TL calls.
*/
tl->rec = &mvol;
/* Fill in the TL access methods */
tl->mapSector = mtlMapSector;
tl->writeSector = mtlWriteSector;
tl->deleteSector = mtlDeleteSector;
#if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)
#ifdef ENVIRONMENT_VARS
if (flMTLdefragMode == FL_MTL_DEFRAGMENT_SEQUANTIAL)
{
tl->defragment = mtlDefragmentAlt;
}
else
#endif /* ENVIRONMENT_VARS */
{
tl->defragment = mtlDefragment;
}
#endif
tl->sectorsInVolume = mtlSectorsInVolume;
tl->getTLInfo = mtlInfo;
tl->tlSetBusy = mtlSetBusy;
tl->dismount = mtlUnmount;
tl->readBBT = NULL /*mtlReadBBT*/;
/*
* The following methods are not supported by NFTL, and have already
* been set to NULL by flMount(). We just confirm this here.
*/
tl->writeMultiSector = NULL;
tl->readSectors = NULL;
tl->recommendedClusterInfo = NULL;
/* Fake the no of volume exported by TrueFFS */
mvol.noOfDrives = noOfDrives;
noOfDrives = 1;
DEBUG_PRINT(("Debug: MTL mount succeeded.\n"));
return status;
}
#ifdef FORMAT_VOLUME
/* -------------------------------------------------------------------------- *
* *
* m t l P r o g r e s s C a l l B a c k *
* *
* Extends the given format routine to report the full media size. *
* *
* Parameters : *
* *
* totalUnitsToFormat : total units needed to format *
* totalUnitsFormattedSoFar : unit formated so far. *
* *
* Notes *
* *
* 1) arguments 0 and 0 initializes the total unit counter to 0. *
* 2) arguments -1 and -1 indicates the ending of the last device. *
* * *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* -------------------------------------------------------------------------- */
static FLStatus mtlProgressCallback(word totalUnitsToFormat,
word totalUnitsFormattedSoFar)
{
static int lastTotal;
static int lastDevice;
/* Initialize lastTotal counter */
if ((totalUnitsToFormat == 0) && (totalUnitsFormattedSoFar == 0))
{
lastTotal = 0;
lastDevice = 0;
return flOK;
}
/* Indicate a new device is being formated */
if ((totalUnitsToFormat == 0) && (totalUnitsFormattedSoFar == 0xffff))
{
lastTotal += lastDevice;
return flOK;
}
/* Call original call back routine */
lastDevice = totalUnitsToFormat;
if (globalProgressCallback == NULL)
{
return flOK;
}
else
{
return globalProgressCallback((word)(lastTotal + totalUnitsToFormat),
(word)(lastTotal + totalUnitsFormattedSoFar));
}
}
/* -------------------------------------------------------------------------- *
* *
* m t l F o r m a t *
* *
* TL's standard volume mount routine. *
* *
* Parameters : *
* *
* volNo : volume #, must be zero *
* formatParams : pointer to the structure containing format *
* parameters *
* flash : MTD attached to the 1st underlaying physical *
* device *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- *
* *
* NOTE. Binary area has 2 possible options: *
* *
* - TL_LEAVE_BINARY_AREA is set - binary area is left for all devices *
* - TL_LEAVE_BINARY_AREA is off - binary area is placed only on the *
* device #0 *
* *
* Handling of 'formatParams.progressCallback' should be improved. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlFormat (unsigned volNo, TLFormatParams* formatParams,
FLFlash *flash)
{
FLFlash tmpFlash;
FLSocket *socket;
FLStatus status = flUnknownMedia;
int iTL, iDev;
/* arg sanity check */
if (volNo != ((unsigned) 0)) {
DEBUG_PRINT(("Debug: can't format, MTL socket # is not zero.\n"));
return flBadParameter;
}
if (formatParams->noOfBDTLPartitions > 1){
DEBUG_PRINT(("Debug: can't format, MTL with more then 1 BDTL volume.\n"));
return flBadParameter;
}
if (formatParams->flags & TL_SINGLE_FLOOR_FORMATTING){
DEBUG_PRINT(("Debug: can't format, MTL does not support single floor formatting.\n"));
return flBadParameter;
}
/* Initialize the progress call back routine to indicate the agregated
* size. The actual routine is saved and mtl routine is used.
*/
globalProgressCallback = formatParams->progressCallback;
formatParams->progressCallback = mtlProgressCallback; /* Set new routine */
mtlProgressCallback(0,0); /* Initialize new format operation */
/*
* Format device #0. Routine flIdentifyFlash() has already been called
* for this device (see arguement 'flash'). Try all TLs registered
* in tlTable[]. Assume MTL is in tlTable[0], so skip it. Skip all the
* TL filters as well.
*/
for (iTL = 1; (iTL < mvol.noOfTLs) && (status == flUnknownMedia); iTL++) {
if (tlTable[iTL].formatRoutine == NULL) /* TL filter */
continue;
status = tlTable[iTL].formatRoutine(0, formatParams, flash);
}
if (status != flOK) {
DEBUG_PRINT(("Debug: no TL recognized device #0, MTL format aborted.\n"));
return status;
}
/*
* Put all 'bootImageLen' and 'exbLen' to the 1st physical device unless
* TL_LEAVE_BINARY_AREA is specified (which means to keep bootimage area
* size as is.
*/
if (!(formatParams->flags & TL_LEAVE_BINARY_AREA))
{
formatParams->bootImageLen = (long) 0;
#ifdef WRITE_EXB_IMAGE
formatParams->exbLen = 0;
#endif /* WRITE_EXB_IMAGE */
formatParams->noOfBinaryPartitions = 0;
}
/*
* Do flash recognition and format for devices #1 .. (mvol.noOfSockets - 1).
* First call flIdentifyFlash() to find MTD, then try all TLs registered
* in tlTable[]. Assume MTL is in tlTable[0], so skip it. Skip all the
* TL filters as well.
*/
for (iDev = 1; iDev < noOfSockets; iDev++) {
socket = flSocketOf (iDev);
status = flIdentifyFlash (socket, &tmpFlash);
if ((status != flOK) && (status != flUnknownMedia)) {
DEBUG_PRINT(("Debug: no MTD recognized the device, MTL format aborted.\n"));
return status;
}
mtlProgressCallback(0,0xffff); /* Initialize new device is being formated */
status = flUnknownMedia;
for (iTL = 1; (iTL < mvol.noOfTLs) && (status == flUnknownMedia); iTL++)
{
if (tlTable[iTL].formatRoutine == NULL) /* TL filter */
continue;
status = tlTable[iTL].formatRoutine (iDev, formatParams, &tmpFlash);
}
if (status != flOK)
{
DEBUG_PRINT(("Debug: no TL recognized the device, MTL format aborted.\n"));
return status;
}
} /* for(iDev) */
DEBUG_PRINT(("Debug: MTL format succeeded.\n"));
return flOK;
}
#endif /* FORMAT_VOLUME */
/* -------------------------------------------------------------------------- *
* *
* f l m t l U n i n s t a l l *
* *
* Removes MTL from the TL table. *
* *
* Note: Must be called after the medium was dismounted. *
* *
* Parameters : *
* *
* none *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
FLStatus flmtlUninstall (void)
{
int iTL;
if (noOfTLs > 0)
{
/* search for MTL in tlTable[] */
for (iTL = 0; iTL < mvol.noOfTLs; iTL++)
{
if (tlTable[iTL].mountRoutine == mtlMount)
break;
}
if (iTL < mvol.noOfTLs)
{
/* MTL is found in tlTable[iTL], so remove it */
for (; iTL < (mvol.noOfTLs - 1); iTL ++)
{
tlTable[iTL].mountRoutine = tlTable[iTL + 1].mountRoutine;
tlTable[iTL].formatRoutine = tlTable[iTL + 1].formatRoutine;
}
tlTable[mvol.noOfTLs - 1].mountRoutine = NULL;
tlTable[mvol.noOfTLs - 1].formatRoutine = NULL;
tlTable[mvol.noOfTLs - 1].preMountRoutine = NULL;
noOfTLs = mvol.noOfTLs - 1;
noOfDrives = mvol.noOfDrives;
}
}
return flOK;
}
/* -------------------------------------------------------------------------- *
* *
* f l m t l I n s t a l l *
* *
* If MTL is found in TL table, it is moved into 1st slot (i.e. effectively *
* enabled). If MTL isn't found in TL table, it is installed into 1st slot. *
* The TL does not increament the number of TL (noOfTLs) global variable, *
* but changes it to 1, therfore reporting it as the only registered TL. *
* *
* Note : The install routine should be the last TL to be regitered. *
* *
* Parameters : *
* *
* none *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
FLStatus flmtlInstall (void)
{
int iTL;
if (noOfTLs > 0)
{
checkStatus( flmtlUninstall() ); /* Dismount previous MTL if exists */
/* Save number of registered TLs and number of volumes */
mvol.noOfTLs = noOfTLs;
mvol.noOfDrives = noOfDrives;
/* search for MTL in tlTable[] */
for (iTL = 0; iTL < noOfTLs; iTL++)
{
if (tlTable[iTL].mountRoutine == mtlMount)
break;
}
if (iTL >= noOfTLs) /* MTL is not found in tlTable[iTL] */
{
/* MTL isn't in tlTable[], we will be adding it */
if (noOfTLs >= TLS)
{
DEBUG_PRINT(("Debug: can't install MTL, too many TLs.\n"));
return flTooManyComponents;
}
iTL = noOfTLs;
mvol.noOfTLs++;
}
else
{
/* MTL is found in tlTable[iTL] */
}
/* free the 1st slot in tlTable[] for MTL */
while (iTL >= 1)
{
tlTable[iTL].mountRoutine = tlTable[iTL - 1].mountRoutine;
tlTable[iTL].formatRoutine = tlTable[iTL - 1].formatRoutine;
iTL--;
}
}
else
{
/* No other TL registered so return error code */
return flMultiDocContrediction;
}
/* Make system believe that only MTL is registered */
noOfTLs = 1;
noOfDrives = 1;
/* put MTL in the 1st slot in tlTable[] */
tlTable[0].mountRoutine = mtlMount;
tlTable[0].preMountRoutine = mtlPreMount;
#ifdef FORMAT_VOLUME
tlTable[0].formatRoutine = mtlFormat;
#else
tlTable[0].formatRoutine = noFormat;
#endif
return flOK;
}
/* -------------------------------------------------------------------------- *
* *
* f l R e g i s t e r M T L *
* *
* Standard TL's component registration routine. *
* *
* Parameters : *
* *
* none *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
FLStatus flRegisterMTL (void)
{
checkStatus( flmtlInstall() );
return flOK;
}
/* Physical routines are not a part of TrueFFS code */
#if 0
/* -------------------------------------------------------------------------- *
* *
* m t l R e a d B B T *
* *
* TL's standard 'read bad blocks table' routine. *
* *
* Parameters : *
* *
* pvol : Pointer identifying drive *
* buf : Pointer to user buffer to read BB info to *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* mediaSize : Size of the formated media *
* noOfBB : Total number of bad blocks read *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlReadBBT (MTL *pvol, byte FAR1 * buf,
long FAR2 * mediaSize, unsigned FAR2 * noOfBB)
{
CardAddress addressShift=0;
long bufOffset = 0;
unsigned tmpCounter;
long tmpMediaSize;
byte iDev;
/* check 'pvol' for sanity */
if (pvol != &mvol)
return flBadDriveHandle;
/* Read bbt of each device while incrementing the address simulating a
* big physical device */
*mediaSize = 0;
*noOfBB = 0;
for (iDev = 0; iDev < noOfSockets; iDev++)
{
checkStatus(mpT(pvol,iDev).readBBT(mpT(pvol,iDev).rec,
(byte FAR1 *)flAddLongToFarPointer(buf,bufOffset),
&tmpMediaSize,&tmpCounter));
*noOfBB += tmpCounter; /* Global BB counter */
for (;tmpCounter>0;tmpCounter--,bufOffset+=sizeof(CardAddress))
{
*((CardAddress *)(buf + bufOffset)) += addressShift;
}
addressShift += mP(iDev);
*mediaSize += tmpMediaSize;
}
return flOK;
}
/* -------------------------------------------------------------------------- *
* *
* m t l W r i t e B B T *
* *
* TL's write Bad Blocks Table routine. *
* *
* Parameters : *
* *
* ioreq : pointer to the structure containing i\o fields *
* *
* Returns : *
* *
* flOK on success, otherwise respective error code. *
* *
* -------------------------------------------------------------------------- */
static FLStatus mtlWriteBBT(IOreq FAR2* ioreq)
{
FLSocket *socket;
FLStatus status;
FLFlash tmpFlash;
CardAddress endUnit;
CardAddress lastDriveAddress;
CardAddress nextDriveAddress = 0;
CardAddress iUnit;
CardAddress bUnit;
CardAddress endAddress;
byte iDev;
word badBlockNo=0;
byte zeroes[2] = {0,0};
/* Initlize last erase address according to argument */
tffsset(&endAddress,0xff,sizeof(CardAddress));
if (ioreq->irLength == 0)
{
tffsset(&endAddress,0xff,sizeof(CardAddress));
}
else
{
endAddress = ioreq->irLength;
}
/*
* Do flash recognition while storing physical size of devices
* #0 .. (mvol.noOfSockets - 1). First call flIdentifyFlash() to find
* MTD, then erase the media while marking bad blocks. Note that the
* addresses are physical addresses of the virtual multi-doc. The address
* should be subtructed by the physical size of the previous devices.
*/
for (iDev = 0; iDev < noOfSockets; iDev++)
{
socket = flSocketOf (iDev);
/* Identify */
status = flIdentifyFlash (socket, &tmpFlash);
if ((status != flOK) && (status != flUnknownMedia))
{
DEBUG_PRINT(("Debug: no MTD recognized the device, MTL writeBBT aborted.\n"));
return status;
}
/* Initialize new drive boundry variables */
mP(iDev) = (dword)(tmpFlash.chipSize * tmpFlash.noOfChips);
lastDriveAddress = nextDriveAddress;
nextDriveAddress += mP(iDev);
endUnit = mP(iDev) >> tmpFlash.erasableBlockSizeBits;
bUnit = ((*((CardAddress FAR1 *)flAddLongToFarPointer
(ioreq->irData,badBlockNo*sizeof(CardAddress)))) -
lastDriveAddress) >> tmpFlash.erasableBlockSizeBits;
/* Erase entire media */
for (iUnit = 0 ,badBlockNo = 0; iUnit < endUnit ; iUnit++)
{
if ((iUnit << tmpFlash.erasableBlockSizeBits) + lastDriveAddress >= endAddress)
return flOK;
tmpFlash.erase(&tmpFlash,iUnit,1);
if (ioreq->irFlags > badBlockNo)
{
if (bUnit == iUnit)
{
tmpFlash.write(&tmpFlash,bUnit <<
tmpFlash.erasableBlockSizeBits,zeroes,2,0);
badBlockNo++;
bUnit = ((*((CardAddress FAR1 *)flAddLongToFarPointer
(ioreq->irData,badBlockNo*sizeof(CardAddress)))) -
lastDriveAddress) >> tmpFlash.erasableBlockSizeBits;
}
}
}
}
return flOK;
}
#endif /* 0 */