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

1571 lines
61 KiB
C
Raw Blame History

/*
* $Log: P:/user/amir/lite/vcs/nfdc2048.c_v $
*
* Rev 1.28 19 Oct 1997 15:41:54 danig
* Changed tffscpy16 and tffsset16 for far pointers &
* cast to FAR0 in mapContInterface
*
* Rev 1.27 06 Oct 1997 18:37:34 ANDRY
* no COBUX
*
* Rev 1.26 06 Oct 1997 18:04:34 ANDRY
* 16-bit access only for interleave 2 cards, COBUX
*
* Rev 1.25 05 Oct 1997 12:02:32 danig
* Support chip ID 0xEA
*
* Rev 1.24 10 Sep 1997 16:14:08 danig
* Got rid of generic names
*
* Rev 1.23 08 Sep 1997 17:47:00 danig
* fixed setAddress for big-endian
*
* Rev 1.22 04 Sep 1997 13:59:44 danig
* Debug messages
*
* Rev 1.21 31 Aug 1997 15:18:04 danig
* Registration routine return status
*
* Rev 1.20 28 Aug 1997 17:47:08 danig
* Buffer\remapped per socket
*
* Rev 1.19 28 Jul 1997 15:10:36 danig
* setPowerOnCallback & moved standard typedefs to flbase.h
*
* Rev 1.18 24 Jul 1997 18:04:12 amirban
* FAR to FAR0
*
* Rev 1.17 21 Jul 1997 18:56:00 danig
* nandBuffer static
*
* Rev 1.16 20 Jul 1997 18:21:14 danig
* Moved vendorID and chipID to Vars
*
* Rev 1.15 20 Jul 1997 17:15:06 amirban
* Added Toshiba 8MB
*
* Rev 1.14 07 Jul 1997 15:22:26 amirban
* Ver 2.0
*
* Rev 1.13 02 Jul 1997 14:59:22 danig
* More wait for socket to power up
*
* Rev 1.12 01 Jul 1997 13:39:54 danig
* Wait for socket to power up
*
* Rev 1.11 22 Jun 1997 18:34:32 danig
* Documentation
*
* Rev 1.10 12 Jun 1997 17:22:24 amirban
* Allow LONG extra read/writes
*
* Rev 1.9 08 Jun 1997 19:18:06 danig
* BIG_PAGE & FULL_PAGE moved to flash.h
*
* Rev 1.8 08 Jun 1997 17:03:40 amirban
* Fast Toshiba and power on callback
*
* Rev 1.7 05 Jun 1997 12:31:38 amirban
* Write corrections, and att reg changes
*
* Rev 1.6 03 Jun 1997 18:45:14 danig
* powerUp()
*
* Rev 1.5 01 Jun 1997 13:42:52 amirban
* Rewrite of read/write extra + major reduction
*
* Rev 1.4 25 May 1997 16:41:38 amirban
* Bg-endian, Toshiba fix & simplifications
*
* Rev 1.3 18 May 1997 17:34:50 amirban
* Use 'dataError'
*
* Rev 1.2 23 Apr 1997 11:02:14 danig
* Update to TFFS revision 1.12
*
* Rev 1.1 15 Apr 1997 18:48:02 danig
* Fixed FAR pointer issues.
*
* Rev 1.0 08 Apr 1997 18:29:28 danig
* Initial revision.
*/
/************************************************************************/
/* */
/* FAT-FTL Lite Software Development Kit */
/* Copyright (C) M-Systems Ltd. 1995-1997 */
/* */
/************************************************************************/
#include "ntddk.h"
#include "flflash.h"
#include "reedsol.h"
#define NFDC2048 /* Support NFDC2048 ASIC controller */
#define MAX_FLASH_DEVICES 16
#define PAGES_PER_BLOCK 16 /* 16 pages per block on a single chip*/
#define SYNDROM_BYTES 6 /* Number of syndrom bytes: 5 + 1 parity*/
/* Flash IDs*/
#define KM29N16000_FLASH 0xec64
#define KM29N32000_FLASH 0xece5
#define KM29V64000_FLASH 0xece6
#define KM29V128000_FLASH 0xec73
#define KM29V256000_FLASH 0xec75
#define NM29N16_FLASH 0x8f64
#define NM29N32_FLASH 0x8fe5
#define NM29N64_FLASH 0x8fe6
#define TC5816_FLASH 0x9864
#define TC5832_FLASH 0x98e5
#define TC5864_FLASH 0x98e6
#define TC58128_FLASH 0x9873
#define TC58256_FLASH 0x9875
/* Flash commands:*/
#define SERIAL_DATA_INPUT 0x80
#define READ_MODE 0x00
#define READ_MODE_2 0x50
#define RESET_FLASH 0xff
#define SETUP_WRITE 0x10
#define SETUP_ERASE 0x60
#define CONFIRM_ERASE 0xd0
#define READ_STATUS 0x70
#define READ_ID 0x90
#define SUSPEND_ERASE 0xb0
#define REGISTER_READ 0xe0
/* commands for moving flash pointer to areeas A,B or C of page*/
typedef enum { AREA_A = READ_MODE, AREA_B = 0x1, AREA_C = READ_MODE_2 } PointerOp;
typedef union { USHORT w ; UCHAR b ; } WordByte;
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Memory window to cards common memory <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
typedef struct
{
volatile WordByte signals; /* CDSN control register*/
#define CE 0x01
#define CLE 0x02
#define ALE 0x04
#define NOT_WP 0x08
#define RB 0x80
#define FAIL 0x01
#define SUSPENDED 0x20
#define READY 0x40
#define NOT_PROTECTED 0x80
UCHAR fillerA[1024 - sizeof(WordByte)];
volatile LEushort deviceSelector;
volatile WordByte eccConfig; /* EDC configuration register*/
#define TOGGLE 0x04 /* Read*/
#ifdef NFDC2048
#define ECC_RST 0x04 /* Write*/
#define ECC_EN 0x08 /* Read / Write*/
#define PAR_DIS 0x10 /* Read / Write*/
#define ECC_RW 0x20 /* Read / Write*/
#define ECC_RDY 0x40 /* Read */
#define ECC_ERROR 0x80 /* Read*/
volatile USHORT syndrom[3];
UCHAR fillerC[1024-10]; /* 1kbytes minus 10 bytes*/
#else
UCHAR fillerC[1024-4]; /* 1kbytes minus 3 words */
#endif /* NFDC2048 */
volatile WordByte io[1024];
} ContComWin;
/* #defines for writing to ContComWin.eccConfig */ /* HOOK - added */
#define SET_ECC_CONFIG(win,val) tffsWriteByteFlash(&((win)->eccConfig.b), (UCHAR)(val))
#define CHK_ECC_ERROR(win) (tffsReadByteFlash(&((win)->eccConfig.b)) & (UCHAR)ECC_ERROR)
typedef ContComWin FAR0 * Interface;
#define DBL(x) ( (UCHAR)(x) * 0x101u )
#define SECOND_TRY 0x8000
#ifdef NFDC2048
/* Controller registers: Addresses & values */
#define ATTRIBUTE_MEM_START 0x8000000L /* Attribute memory starts at 128MB */
/* Controller configuration register */
#define CONFIG1 ATTRIBUTE_MEM_START + 0x3ffc
#define PWR_DN 0x01 /* Read / Write*/
#define PWR_DN2 0x02 /* Read / Write*/
#define STOP_CDSN 0x04 /* Read / Write*/
#define STOP_CDSNS 0x08 /* Read / Write*/
#define C_CDSN 0x10 /* Read / Write*/
#define R_CDSN 0x20 /* Read / Write*/
#define WP_C 0x40 /* Read / Write*/
#define WP_A 0x80 /* Read / Write*/
/* board's jumper settings*/
#define JUMPERS ATTRIBUTE_MEM_START + 0x3ffe
#define JMPER_INLV 0x08
#define JMPER_CDSNS 0x10
#define JMPER_EXT_CIS 0x20
#define JMPER_LDR_MASK 0x40
#define JMPER_MAX_MODE 0x80
/* PCMCIA register #0*/
#define CONFIG_OPTION ATTRIBUTE_MEM_START + 0x4000
#define CONFIGIDX 0x3F /* Read / Write*/
#define SREST 0x80 /* Read / Write*/
/* PCMCIA register #1*/
#define CARD_CONFIG ATTRIBUTE_MEM_START + 0x4002
#define PWRDWN 0x04 /* Read / Write*/
#else
#define INLV 2 /* Must define interleaving statically */
#endif /* NFDC2048 */
/* customization for this MTD*/
/*#define MULTI_ERASE */ /* use multiple block erase feature*/
#define USE_EDC /* use Error Detection /Correction Code */
/* #define VERIFY_AFTER_WRITE */
typedef struct {
USHORT vendorID;
USHORT chipID;
USHORT pageSize ; /* all....................*/
USHORT pageMask ; /* ...these...............*/
USHORT pageAreaSize ; /* .......variables.......*/
USHORT tailSize ; /* .............interleave*/
USHORT noOfBlocks ; /* total erasable blocks in flash device*/
USHORT pagesPerBlock; /* number of pages per block */
FLBuffer *buffer; /* buffer for map through buffer */
} Vars;
Vars mtdVars_nfdc2048[SOCKETS];
#define thisVars ((Vars *) vol.mtdVars)
#define thisBuffer (thisVars->buffer->flData)
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Auxiliary methods <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
/*----------------------------------------------------------------------*/
/* t f f s c p y 1 6 */
/* */
/* Move data in 16-bit words. */
/* */
/* Parameters: */
/* dst : destination buffer */
/* src : source buffer */
/* len : bytes to move */
/* */
/*----------------------------------------------------------------------*/
VOID tffscpy16fromMedia (UCHAR FAR0 *dst,
const UCHAR FAR0 *src,
LONG len)
{
register LONG i;
USHORT FAR0 *dstPtr = (USHORT FAR0 *) dst;
const USHORT FAR0 *srcPtr = (USHORT FAR0 *) src;
/* move data in 16-bit words */
for (i = len; i > 0; i -= 2)
*dstPtr++ = tffsReadWordFlash(srcPtr++);
}
VOID tffscpy16toMedia (UCHAR FAR0 *dst,
const UCHAR FAR0 *src,
LONG len)
{
register LONG i;
USHORT FAR0 *dstPtr = (USHORT FAR0 *) dst;
const USHORT FAR0 *srcPtr = (USHORT FAR0 *) src;
/* move data in 16-bit words */
for (i = len; i > 0; i -= 2)
tffsWriteWordFlash(dstPtr++,*srcPtr++);
}
/*----------------------------------------------------------------------*/
/* t f f s s e t 1 6 */
/* */
/* Set data buffer in 16-bit words. */
/* */
/* Parameters: */
/* dst : destination buffer */
/* val : byte value tofill the buffer */
/* len : setination buffer size in bytes */
/* */
/*----------------------------------------------------------------------*/
VOID tffsset16 (UCHAR FAR0 *dst,
UCHAR val,
LONG len)
{
register USHORT wval = ((USHORT)val << 8) | val;
register LONG i = 0;
USHORT FAR0 *dstPtr;
/* set data in 16-bit words */
for (i = 0; i < len - 1; i += 2) {
dstPtr = (USHORT FAR0 *)addToFarPointer(dst, i);
tffsWriteWordFlash(dstPtr,wval);
}
/* set last byte (if any) */
if (len & 1) {
dstPtr = (USHORT FAR0 *)addToFarPointer(dst, len - 1);
tffsWriteByteFlash(dstPtr,wval);
}
}
#ifdef NFDC2048
/*----------------------------------------------------------------------*/
/* r e a d S y n d r o m */
/* */
/* Read ECC syndrom and swap words to prepare it for writing to flash. */
/* */
/* Parameters: */
/* Interface : Pointer to window. */
/* to : buffer to read to. */
/* */
/*----------------------------------------------------------------------*/
VOID readSyndrom_nfdc2048( Interface interface, USHORT *to )
{
to[0] = tffsReadWordFlash(&(interface->syndrom[2]));
to[1] = tffsReadWordFlash(&(interface->syndrom[1]));
to[2] = tffsReadWordFlash(&(interface->syndrom[0]));
}
#ifdef USE_EDC
/*----------------------------------------------------------------------*/
/* r e a d S y n d r o m O n S y n d r o m */
/* */
/* Read ECC syndrom. */
/* */
/* Parameters: */
/* Interface : Pointer to window. */
/* to : buffer to read to. */
/* */
/*----------------------------------------------------------------------*/
VOID readSyndromOnSyndrom ( Interface interface, USHORT *to )
{
to[0] = tffsReadWordFlash(&(interface->syndrom[0]));
to[1] = tffsReadWordFlash(&(interface->syndrom[1]));
to[2] = tffsReadWordFlash(&(interface->syndrom[2]));
}
#endif /* USE_EDC */
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Miscellaneous routines <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
/*----------------------------------------------------------------------*/
/* g e t A t t R e g */
/* */
/* Get ASIC register residing in card's Attribute memory. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : Address of register. */
/* */
/* Returns: */
/* Value of register. */
/* */
/*----------------------------------------------------------------------*/
UCHAR getAttReg(FLFlash vol, CardAddress reg)
{
return (UCHAR) (tffsReadByteFlash((USHORT FAR0 *) flMap(vol.socket,reg)));
}
/*----------------------------------------------------------------------*/
/* s e t A t t R e g */
/* */
/* Set ASIC register residing in card's Attribute memory. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : Address of register. */
/* value : Value to set */
/* */
/*----------------------------------------------------------------------*/
VOID setAttReg(FLFlash vol, CardAddress reg, UCHAR value)
{
tffsWriteWordFlash((USHORT FAR0 *) flMap(vol.socket,reg), DBL(value));
}
/*----------------------------------------------------------------------*/
/* p o w e r U p */
/* */
/* Power up the controller. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* */
/*----------------------------------------------------------------------*/
VOID powerUp(VOID *pVol)
{
flDelayMsecs(1);
setAttReg ((FLFlash *) pVol, CONFIG1, WP_C); /* Power up the controller */
}
#endif /* NFDC2048 */
/*----------------------------------------------------------------------*/
/* m a p C o n t I n t e r f a c e */
/* */
/* Select flash device. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : Address in flash. */
/* */
/* Returns: */
/* Pointer to the mapped window. */
/* */
/*----------------------------------------------------------------------*/
Interface mapContInterface(FLFlash vol, CardAddress address)
{
Interface interface = (Interface) flMap(vol.socket,(CardAddress)0);
LEushort tmp;
toLE2(*((LEushort FAR0 *) &tmp), (USHORT)(address / (vol.chipSize * vol.interleaving)));
/* Select flash device with 16-bit write */
tffsWriteWordFlash(((USHORT FAR0 *) &interface->deviceSelector), *((USHORT *) &tmp));
return interface;
}
/*----------------------------------------------------------------------*/
/* w a i t F o r R e a d y */
/* */
/* Wait for the selected device to be ready. */
/* */
/* Parameters: */
/* Interface : Pointer tot the window. */
/* */
/* Returns: */
/* TRUE if device is ready, FALSE if timeout error. */
/* */
/*----------------------------------------------------------------------*/
FLBoolean waitForReady_nfdc2048 (Interface interface)
{
LONG i;
for( i = 0; i < 20000; i++)
{
if( (~(tffsReadWordFlash(&(interface->signals.w))) & DBL(RB)) == 0)
return TRUE ; /* ready at last..*/
flDelayMsecs(1);
}
DEBUG_PRINT(("Debug: timeout error in NFDC 2048.\n"));
return FALSE; /* timeout error */
}
/*----------------------------------------------------------------------*/
/* m a k e C o m m a n d */
/* */
/* Set Page Pointer to Area A, B or C in page. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* cmd : receives command relevant to area */
/* addr : receives the address to the right area. */
/* modes : mode of operation (EXTRA ...) */
/* */
/*----------------------------------------------------------------------*/
VOID makeCommand_nfdc2048 (FLFlash vol, PointerOp *cmd, CardAddress *addr , LONG modes )
{
USHORT offset;
if ( !(vol.flags & BIG_PAGE) ) {
if (modes & EXTRA) {
offset = (USHORT) (*addr & (SECTOR_SIZE - 1));
*cmd = AREA_C;
if (vol.interleaving == 1) {
if (offset < 8) /* First half of extra area */
*addr += 0x100; /* ... assigned to 2nd page */
else /* Second half of extra area */
*addr -= 8; /* ... assigned to 1st page */
}
}
else
*cmd = AREA_A;
}
else {
offset = (USHORT)(*addr) & thisVars->pageMask ; /* offset within device Page */
*addr -= offset; /* align at device Page*/
if (vol.interleaving == 2 && offset >= 512)
offset += 16; /* leave room for 1st extra area */
if (modes & EXTRA)
offset += SECTOR_SIZE;
if ( offset < thisVars->pageAreaSize ) /* starting in area A*/
*cmd = AREA_A ;
else if ( offset < thisVars->pageSize ) /* starting in area B */
*cmd = AREA_B ;
else /* got into area C*/
*cmd = AREA_C ;
offset &= (thisVars->pageAreaSize - 1) ; /* offset within area of device Page*/
*addr += offset ;
}
}
/*----------------------------------------------------------------------*/
/* c o m m a n d */
/* */
/* Latch command byte to selected flash device. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* Interface : Pointer to window. */
/* code : Command to set. */
/* */
/*----------------------------------------------------------------------*/
VOID command2048(FLFlash vol, Interface interface, UCHAR code)
{
tffsWriteWordFlash(&(interface->signals.w), DBL( CLE | NOT_WP | CE ));
if ( vol.interleaving == 1 ) { /* 8-bit */
tffsWriteByteFlash(&(interface->io[0].b), code);
} else { /* 16-bit */
tffsWriteWordFlash(&(interface->io[0].w), DBL( code ));
}
tffsWriteWordFlash(&(interface->signals.w), DBL( NOT_WP ));
}
/*----------------------------------------------------------------------*/
/* s e t A d d r e s s */
/* */
/* Latch address to selected flash device. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* Interface : Pointer to window. */
/* address : address to set. */
/* */
/*----------------------------------------------------------------------*/
VOID setAddress2048(FLFlash vol, Interface interface, CardAddress address )
{
address &= (vol.chipSize * vol.interleaving - 1) ; /* address within flash device*/
address /= vol.interleaving ; /* .................... chip */
if ( vol.flags & BIG_PAGE )
{
/*
bits 0..7 stays as are
bit 8 is thrown away from address
bits 31..9 -> bits 30..8
*/
address = ((address >> 9) << 8) | ((UCHAR)address) ;
}
tffsWriteWordFlash(&(interface->signals.w), DBL(ALE | NOT_WP | CE));
/* send address to flash in the following sequence: */
/* bits 7...0 first */
/* bits 15...8 next */
/* bits 23..16 finally */
if ( vol.interleaving == 1 )
{
tffsWriteByteFlash(&(interface->io[0].b), (UCHAR)address );
tffsWriteByteFlash(&(interface->io[0].b), (UCHAR)(address >> 8));
tffsWriteByteFlash(&(interface->io[0].b), (UCHAR)(address >> 16));
}
else
{
tffsWriteWordFlash(&(interface->io[0].w), (USHORT)DBL(address));
tffsWriteWordFlash(&(interface->io[0].w), (USHORT)DBL(address >> 8));
tffsWriteWordFlash(&(interface->io[0].w), (USHORT)DBL(address >> 16));
}
tffsWriteWordFlash(&(interface->signals.w), DBL( NOT_WP | CE));
}
/*----------------------------------------------------------------------*/
/* r e a d C o m m a n d */
/* */
/* Issue read command. */
/* */
/* Parametes: */
/* vol : Pointer identifying drive */
/* Interface : Pointer to window. */
/* cmd : Command to issue (according to area). */
/* addr : address to read from. */
/* */
/*----------------------------------------------------------------------*/
VOID readCommand2048 (FLFlash vol, Interface interface, PointerOp cmd, CardAddress addr)
{
command2048 (&vol, interface, (UCHAR) cmd) ; /* move flash pointer to respective area of the page*/
setAddress2048 (&vol, interface, addr) ;
waitForReady_nfdc2048(interface) ;
}
/*----------------------------------------------------------------------*/
/* w r i t e C o m m a n d */
/* */
/* Issue write command. */
/* */
/* Parametes: */
/* vol : Pointer identifying drive */
/* interface : Pointer to window. */
/* cmd : Command to issue (according to area). */
/* addr : address to write to. */
/* */
/*----------------------------------------------------------------------*/
VOID writeCommand2048 (FLFlash vol, Interface interface, PointerOp cmd, CardAddress addr)
{
if (vol.flags & FULL_PAGE) {
command2048 (&vol, interface, RESET_FLASH); /* Clear page buffer */
waitForReady_nfdc2048(interface);
}
command2048 (&vol, interface, (UCHAR) cmd) ; /* move flash pointer to respective area of the page */
command2048 (&vol, interface, SERIAL_DATA_INPUT); /* start data loading for write */
setAddress2048 (&vol, interface, addr) ;
}
/*----------------------------------------------------------------------*/
/* r e a d S t a t u s */
/* */
/* Read status of selected flash device. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* interface : Pointer to window. */
/* */
/* Returns: */
/* Chip status. */
/* */
/*----------------------------------------------------------------------*/
USHORT readStatus2048(FLFlash vol, Interface interface)
{
USHORT chipStatus ;
command2048(&vol, interface, READ_STATUS);
tffsWriteWordFlash(&(interface->signals.w), DBL( NOT_WP | CE ));
if ( vol.interleaving == 1 ) /* 8-bit*/
chipStatus = DBL(tffsReadByteFlash(&(interface->io[0].b)));
else /* 16-bit */
chipStatus = tffsReadWordFlash(&(interface->io[0].w));
tffsWriteWordFlash(&(interface->signals.w), DBL( NOT_WP ));
return chipStatus;
}
/*----------------------------------------------------------------------*/
/* w r i t e E x e c u t e */
/* */
/* Execute write. */
/* */
/* Parametes: */
/* vol : Pointer identifying drive */
/* interface : Pointer to window. */
/* Returns: */
/* FLStatus : 0 on success, otherwise failed. */
/* */
/*----------------------------------------------------------------------*/
FLStatus writeExecute2048 (FLFlash vol, Interface interface)
{
command2048 (&vol, interface, SETUP_WRITE); /* execute page program*/
if (!waitForReady_nfdc2048(interface)) {
return flTimedOut;
}
if( readStatus2048(&vol, interface) & DBL(FAIL) )
return flWriteFault ;
return flOK ;
}
/*----------------------------------------------------------------------*/
/* r e a d O n e S e c t o r */
/* */
/* Read up to one 512-byte block from flash. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : Address to read from. */
/* buffer : buffer to read to. */
/* length : number of bytes to read (up to sector size). */
/* modes : EDC flag etc. */
/* */
/* Returns: */
/* FLStatus: 0 on success, otherwise failed. */
/* */
/*----------------------------------------------------------------------*/
FLStatus readOneSector_nfdc2048 (FLFlash vol,
CardAddress address, /* starting flash address*/
CHAR FAR1 *buffer, /* target buffer */
LONG length, /* bytes to read */
LONG modes) /* EDC flag etc.*/
{
FLStatus status = flOK;
PointerOp cmd;
CardAddress addr = address ;
Interface interface = mapContInterface(&vol, address); /* select flash device */
/* move flash pointer to areas A,B or C of page*/
makeCommand_nfdc2048 (&vol, &cmd, &addr, modes) ;
readCommand2048 (&vol, interface, cmd, addr);
#ifdef NFDC2048
if(modes & EDC) {
SET_ECC_CONFIG(interface, ECC_RST | ECC_EN); /*ECC reset and ON for read*/
}
#endif /* NFDC2048 */
if ((vol.interleaving == 1) && !(vol.flags & BIG_PAGE) ) /* 8-bit */
{
/* read up to two pages separately, starting page.. */
LONG toFirstPage, toSecondPage;
toFirstPage = (cmd == AREA_C ? 8 : 0x100) -
((USHORT)address & (cmd == AREA_C ? 7 : 0xff));
if (toFirstPage > length)
toFirstPage = length;
toSecondPage = length - toFirstPage ;
tffscpy16fromMedia ((UCHAR*)buffer, (const UCHAR FAR0 *) interface->io, toFirstPage ) ;
if ( toSecondPage > 0 )
{
/* next page*/
readCommand2048 (&vol, interface, AREA_A, address + toFirstPage) ;
tffscpy16fromMedia( (UCHAR*)(buffer + toFirstPage),
(const UCHAR FAR0 *) interface->io,
toSecondPage ) ;
}
}
else /* interleaving == 2 so 16-bit read*/
tffscpy16fromMedia( (UCHAR*)buffer, (const UCHAR FAR0 *) interface->io, length );
#ifdef NFDC2048
if( modes & EDC )
{
UCHAR extraBytes[SYNDROM_BYTES];
/* read syndrom to let it through the ECC unit*/
SET_ECC_CONFIG(interface, ECC_EN | PAR_DIS); /* parity off in ECC*/
tffscpy16fromMedia( extraBytes, (const UCHAR FAR0 *) interface->io, SYNDROM_BYTES ) ;
if( CHK_ECC_ERROR(interface) ) /* ECC error*/
{
if( (vol.interleaving == 1) && !(vol.flags & BIG_PAGE) )
{ /* HOOK : make ECC working on 2M /INLV 1 */ }
else
{
#ifdef USE_EDC
/* try to fix ECC error*/
if ( modes & SECOND_TRY ) /* 2nd try*/
{
UCHAR syndrom[SYNDROM_BYTES];
/* read syndrom-on-syndrom from ASIC*/
readSyndromOnSyndrom(interface, (USHORT*)syndrom );
if (flCheckAndFixEDC(buffer, (CHAR FAR1 *)syndrom, vol.interleaving == 2) != NO_EDC_ERROR) {
DEBUG_PRINT(("Debug: ECC error in NFDC 2048.\n"));
status = flDataError;
}
}
else /* 1st try - try once more*/
{
SET_ECC_CONFIG(interface, PAR_DIS); /* reset ECC*/
return readOneSector_nfdc2048(&vol, address, buffer, length, modes | SECOND_TRY ) ;
}
#endif /* USE_EDC*/
}
}
SET_ECC_CONFIG(interface, PAR_DIS); /* ECC off*/
}
#endif /* NFDC2048 */
interface->signals.w = DBL(NOT_WP) ;
return status;
}
/*----------------------------------------------------------------------*/
/* w r i t e O n e S e c t o r */
/* */
/* Write data in one 512-byte block to flash. */
/* Assuming that EDC mode never requested on partial block writes. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : Address of sector to write to. */
/* buffer : buffer to write from. */
/* length : number of bytes to write (up to sector size). */
/* modes : OVERWRITE, EDC flags etc. */
/* */
/* Returns: */
/* FLStatus: 0 on success, otherwise failed. */
/* */
/*----------------------------------------------------------------------*/
FLStatus writeOneSector_nfdc2048(FLFlash vol,
CardAddress address, /* target flash addres */
const CHAR FAR1 *buffer, /* source RAM buffer */
LONG length, /* bytes to write (up to BLOCK) */
LONG modes) /* OVERWRITE, EDC flags etc. */
{
FLStatus status;
PointerOp cmd;
Interface interface = mapContInterface(&vol, address); /* select flash device*/
if (flWriteProtected(vol.socket))
return flWriteProtect;
/* move flash pointer to areas A,B or C of page */
makeCommand_nfdc2048 (&vol, &cmd, &address, modes) ;
if ((vol.flags & FULL_PAGE) && cmd == AREA_B) {
ULONG prePad = 2 + ((USHORT) address & thisVars->pageMask);
writeCommand2048(&vol, interface, AREA_A, address + thisVars->pageAreaSize - prePad);
tffsset16( (UCHAR FAR0 *) interface->io, 0xff, prePad);
}
else
writeCommand2048(&vol, interface, cmd, address);
#ifdef NFDC2048
if (modes & EDC)
SET_ECC_CONFIG(interface, ECC_EN | ECC_RW); /* ECC ON for write*/
#endif
/* load data and syndrom*/
if( (vol.interleaving == 1) && !(vol.flags & BIG_PAGE) ) /* 8-bit*/
{
LONG toFirstPage, toSecondPage ;
/* write up to two pages separately*/
toFirstPage = (modes & EXTRA ? 8 : 0x100) -
((USHORT)address & (modes & EXTRA ? 7 : 0xff));
if (toFirstPage > length)
toFirstPage = length;
toSecondPage = length - toFirstPage ;
tffscpy16toMedia( (UCHAR FAR0 *) interface->io, /* user data */
(const UCHAR *)buffer,
toFirstPage);
if ( toSecondPage > 0 )
{
checkStatus( writeExecute2048(&vol, interface) ) ; /* done with 1st page */
writeCommand2048(&vol, interface, AREA_A, address + toFirstPage);
/* user data*/
tffscpy16toMedia( (UCHAR FAR0 *) interface->io,
(const UCHAR *)(buffer + toFirstPage),
toSecondPage);
}
}
else /* 16-bit*/
tffscpy16toMedia( (UCHAR FAR0 *) interface->io, /* user data*/
(const UCHAR *)buffer,
length );
if(modes & EDC)
{
USHORT extraBytes[SYNDROM_BYTES / sizeof(USHORT) + 1];
/* Read the ECC syndrom*/
#ifdef NFDC2048
tffsWriteWordFlash(&(interface->signals.w), DBL(NOT_WP));
SET_ECC_CONFIG(interface, ECC_EN | PAR_DIS | ECC_RW); /* ECC parity off*/
readSyndrom_nfdc2048( interface, (USHORT*)extraBytes) ;
/* Write ECC syndrom and ANAND mark to the tail*/
SET_ECC_CONFIG(interface, PAR_DIS); /* ECC off*/
interface->signals.w = DBL(NOT_WP | CE);
#else
extraBytes[0] = extraBytes[1] = extraBytes[2] = 0xffff;
#endif /* NFDC2048 */
extraBytes[SYNDROM_BYTES / sizeof(USHORT)] = 0x5555; /* Anand mark */
tffscpy16toMedia((UCHAR FAR0 *) interface->io, (const UCHAR *)extraBytes,
sizeof extraBytes);
}
status = writeExecute2048(&vol, interface);
tffsWriteWordFlash(&(interface->signals.w), DBL(NOT_WP));
return status;
}
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
<20> Core MTD methods - read, write and erase <20>
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
/*----------------------------------------------------------------------*/
/* c d s n R e a d */
/* */
/* Read some data from the flash. This routine will be registered as */
/* the read routine for this MTD. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : Address to read from. */
/* buffer : buffer to read to. */
/* length : number of bytes to read (up to sector size). */
/* modes : EDC flag etc. */
/* */
/* Returns: */
/* FLStatus: 0 on success, otherwise failed. */
/* */
/*----------------------------------------------------------------------*/
FLStatus cdsnRead( FLFlash vol,
CardAddress address, /* target flash address */
VOID FAR1 *buffer, /* source RAM buffer */
dword length, /* bytes to write */
word modes) /* Overwrite, EDC flags etc. */
{
CHAR FAR1 *temp;
ULONG readNow;
/* read in sectors; first and last might be partial*/
ULONG block = modes & EXTRA ? 8 : SECTOR_SIZE;
readNow = block - ((USHORT)address & (block - 1));
temp = (CHAR FAR1 *)buffer;
for ( ; length > 0 ; )
{
if (readNow > length)
readNow = length;
/* turn off EDC on partial block read*/
checkStatus( readOneSector_nfdc2048(&vol, address, temp, readNow,
(readNow != SECTOR_SIZE ? (modes & ~EDC) : modes)) );
length -= readNow;
address += readNow;
temp += readNow;
/* align at sector */
readNow = block;
}
return flOK ;
}
/*----------------------------------------------------------------------*/
/* c d s n W r i t e */
/* */
/* Write some data to the flash. This routine will be registered as the */
/* write routine for this MTD. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : Address of sector to write to. */
/* buffer : buffer to write from. */
/* length : number of bytes to write (up to sector size). */
/* modes : OVERWRITE, EDC flags etc. */
/* */
/* Returns: */
/* FLStatus: 0 on success, otherwise failed. */
/* */
/*----------------------------------------------------------------------*/
FLStatus cdsnWrite( FLFlash vol,
CardAddress address, /* target flash address*/
const VOID FAR1 *buffer, /* source RAM buffer */
dword length, /* bytes to write */
word modes) /* Overwrite, EDC flags etc.*/
{
ULONG writeNow;
const CHAR FAR1 *temp;
FLStatus status = flOK;
#ifdef VERIFY_AFTER_WRITE
CardAddress saveAddress = address;
USHORT flReadback[SECTOR_SIZE / sizeof(USHORT)];
#endif
/* write in sectors; first and last might be partial*/
LONG block = modes & EXTRA ? 8 : SECTOR_SIZE;
writeNow = block - ((USHORT)address & (block - 1));
temp = (const CHAR FAR1 *)buffer;
for ( ; length > 0 ; )
{
if (writeNow > length)
writeNow = length;
/* turn off EDC on partial block write*/
status = writeOneSector_nfdc2048(&vol, address, temp, writeNow,
writeNow != SECTOR_SIZE ? (modes & ~EDC) : modes);
if (status != flOK)
break;
#ifdef VERIFY_AFTER_WRITE
status = readOneSector_nfdc2048 (&vol, address, (CHAR FAR1 *)flReadback,
writeNow, (writeNow != SECTOR_SIZE ? (modes & ~EDC) : modes));
if((status != flOK) || (tffscmp(temp, flReadback, writeNow) != 0))
{ status = flWriteFault; break; }
#endif
length -= writeNow;
address += writeNow;
temp += writeNow;
/* align at sector */
writeNow = block;
}
return flOK ;
}
/*----------------------------------------------------------------------*/
/* c d s n E r a s e */
/* */
/* Erase number of blocks. This routine will be registered as the */
/* erase routine for this MTD. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* blockNo : First block to erase. */
/* blocksToErase : Number of blocks to erase. */
/* */
/* Returns: */
/* FLStatus : 0 on success, otherwise failed. */
/* */
/*----------------------------------------------------------------------*/
FLStatus cdsnErase( FLFlash vol,
word blockNo, /* start' block (0 .. chipNoOfBlocks-1)*/
word blocksToErase) /* Number of blocks to be erased */
{
LONG i;
FLStatus status = flOK;
Interface interface =
mapContInterface(&vol, (LONG)blockNo * vol.erasableBlockSize ) ; /* select device*/
if (flWriteProtected(vol.socket))
return flWriteProtect;
blockNo %= thisVars->noOfBlocks ; /* within flash device */
if ( blockNo + blocksToErase > thisVars->noOfBlocks ) /* accross device boundary */
return flBadParameter;
for ( i=0 ; i < blocksToErase ; i++, blockNo++ )
{
USHORT pageNo = (USHORT) (blockNo * thisVars->pagesPerBlock);
command2048(&vol, interface, SETUP_ERASE);
tffsWriteWordFlash(&(interface->signals.w), DBL(ALE | NOT_WP | CE));
/* send 'pageNo' to the flash in the following sequence: */
/* bits 7..0 first */
/* bits 15..8 next */
if (vol.interleaving == 1)
{
tffsWriteByteFlash(&(interface->io[0].b),(UCHAR)pageNo);
tffsWriteByteFlash(&(interface->io[0].b),(UCHAR)(pageNo >> 8));
}
else
{
tffsWriteWordFlash(&(interface->io[0].w), DBL(pageNo));
tffsWriteWordFlash(&(interface->io[0].w), DBL(pageNo >> 8));
}
tffsWriteWordFlash(&(interface->signals.w), DBL(NOT_WP | CE));
/* if only one block may be erase at a time then do it
otherwise leave it for later*/
command2048(&vol, interface, CONFIRM_ERASE);
if (!waitForReady_nfdc2048(interface))
status = flTimedOut;
if ( readStatus2048(&vol, interface) & DBL(FAIL)) { /* erase operation failed*/
status = flWriteFault ;
}
if (status != flOK) { /* reset flash device and abort */
DEBUG_PRINT(("Debug: erase failed in NFDC 2048.\n"));
command2048(&vol, interface, RESET_FLASH ) ;
waitForReady_nfdc2048(interface) ;
break ;
}
} /* block loop */
#ifdef MULTI_ERASE
/* do multiple block erase as was promised*/
command2048(&vol, interface, CONFIRM_ERASE);
if (!waitForReady_nfdc2048(interface))
status = flTimedOut;
if ( readStatus2048(interface) & DBL(FAIL)) { /* erase operation failed*/
status = flWriteFault ;
}
if (status != flOK) { /* reset flash device and abort*/
DEBUG_PRINT(("Debug: erase failed in NFDC 2048.\n"));
command2048(&vol, interface, RESET_FLASH ) ;
waitForReady_nfdc2048(interface) ;
}
#endif /* MULTI_ERASE*/
if(status == flOK)
if ( readStatus2048(&vol, interface) & DBL(FAIL) ) {
DEBUG_PRINT(("Debug: erase failed in NFDC 2048.\n"));
status = flWriteFault;
}
return status;
}
/*----------------------------------------------------------------------*/
/* c d s n M a p */
/* */
/* Map through buffer. This routine will be registered as the map */
/* routine for this MTD. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : Flash address to be mapped. */
/* length : number of bytes to map. */
/* */
/* Returns: */
/* Pointer to the buffer data was mapped to. */
/* */
/*----------------------------------------------------------------------*/
VOID FAR0 * cdsnMap ( FLFlash vol,
CardAddress address,
int length )
{
cdsnRead(&vol,address,thisBuffer,length, 0);
vol.socket->remapped = TRUE;
return (VOID FAR0 *)thisBuffer;
}
#ifdef NFDC2048
/*----------------------------------------------------------------------*/
/* c d s n S e t C a l l b a c k */
/* */
/* Register a routine (powerUp()) for power on callback. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* */
/*----------------------------------------------------------------------*/
VOID cdsnSetCallback(FLFlash vol)
{
flSetPowerOnCallback(vol.socket, powerUp, &vol);
}
#endif /* NFDC2048 */
/*----------------------------------------------------------------------*/
/* i s K n o w n M e d i a */
/* */
/* Check if this flash media is supported. Initialize relevant fields */
/* in data structures. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* vendorId_P : vendor ID read from chip. */
/* chipId_p : chip ID read from chip. */
/* dev : dev chips were accessed before this one. */
/* */
/* Returns: */
/* TRUE if this media is supported, FALSE otherwise. */
/* */
/*----------------------------------------------------------------------*/
FLBoolean isKnownMedia_nfdc2048( FLFlash vol,
USHORT vendorId_p,
USHORT chipId_p,
LONG dev )
{
#ifdef NFDC2048
if ((chipId_p & 0xff00) == 0x6400)
chipId_p = DBL(0x64); /* Workaround for TC5816/NFDC2048 problem */
#endif /* NFDC2048 */
if (dev == 0)
{
thisVars->vendorID = vendorId_p; /* remember for next chips */
thisVars->chipID = chipId_p;
thisVars->pagesPerBlock = PAGES_PER_BLOCK;
if (vendorId_p == DBL(0xEC)) /* Samsung */
{
switch (chipId_p)
{
case DBL(0x64): /* 2M */
case DBL(0xEA) :
vol.type = KM29N16000_FLASH ;
vol.chipSize = 0x200000L;
return TRUE;
case DBL(0xE5):
case DBL(0xE3): /* 4M */
vol.type = KM29N32000_FLASH;
vol.flags |= BIG_PAGE;
vol.chipSize = 0x400000L;
return TRUE;
case DBL(0xE6): /* 8M */
vol.type = KM29V64000_FLASH;
vol.flags |= BIG_PAGE;
vol.chipSize = 0x800000L;
return TRUE;
case DBL(0x73): /* 16 Mb */
vol.type = KM29V128000_FLASH;
vol.flags |= BIG_PAGE;
vol.chipSize = 0x1000000L;
thisVars->pagesPerBlock *= 2;
return TRUE;
case DBL(0x75): /* 32 Mb */
vol.type = KM29V256000_FLASH;
vol.flags |= BIG_PAGE;
vol.chipSize = 0x2000000L;
thisVars->pagesPerBlock *= 2;
return TRUE;
}
}
else
if (vendorId_p == DBL(0x8F)) /* National */
{
switch (chipId_p)
{
case DBL(0x64): /* 2M */
vol.type = NM29N16_FLASH;
vol.chipSize = 0x200000L;
return TRUE;
}
}
else
if (vendorId_p == DBL(0x98)) /* Toshiba */
{
vol.flags |= FULL_PAGE; /* no partial page programming */
switch (chipId_p)
{
case DBL(0x64): /* 2M */
case DBL(0xEA) :
vol.type = TC5816_FLASH;
vol.chipSize = 0x200000L;
return TRUE;
case DBL(0x6B): /* 4M */
case DBL(0xE5):
vol.type = TC5832_FLASH;
vol.flags |= BIG_PAGE;
vol.chipSize = 0x400000L;
return TRUE;
case DBL(0xE6): /* 8M */
vol.type = TC5816_FLASH;
vol.flags |= BIG_PAGE;
vol.chipSize = 0x800000L;
return TRUE;
case DBL(0x73): /* 16 Mb */
vol.type = TC58128_FLASH;
vol.flags |= BIG_PAGE;
vol.chipSize = 0x1000000L;
thisVars->pagesPerBlock *= 2;
return TRUE;
case DBL(0x75): /* 32 Mb */
vol.type = TC58256_FLASH;
vol.flags |= BIG_PAGE;
vol.chipSize = 0x2000000L;
thisVars->pagesPerBlock *= 2;
return TRUE;
}
}
}
else /* dev != 0*/
if( (vendorId_p == thisVars->vendorID) && (chipId_p == thisVars->chipID) )
return TRUE ;
return FALSE ;
}
/*----------------------------------------------------------------------*/
/* r e a d F l a s h I D */
/* */
/* Read vendor and chip IDs, count flash devices. Initialize relevant */
/* fields in data structures. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* interface : Pointer to window. */
/* dev : dev chips were accessed before this one. */
/* */
/* Returns: */
/* TRUE if this media is supported, FALSE otherwise. */
/* */
/*----------------------------------------------------------------------*/
LONG readFlashID2048 (FLFlash vol, Interface interface, LONG dev)
{
USHORT vendorId_p, chipId_p ;
KeStallExecutionProcessor(250 * 1000);
command2048(&vol, interface, RESET_FLASH ) ;
flDelayMsecs(10);
command2048(&vol, interface, READ_ID);
tffsWriteWordFlash(&(interface->signals.w), DBL(ALE | NOT_WP | CE));
if (vol.interleaving == 1) {
tffsWriteByteFlash(&(interface->io[0].b), 0); /* Read ID from*/
} else { /* address 0. */
tffsWriteWordFlash(&(interface->io[0].w), 0);
}
tffsWriteWordFlash(&(interface->signals.w), DBL(NOT_WP | CE));
/* read vendor and chip IDs */
vendorId_p = (vol.interleaving == 1 ? DBL(tffsReadByteFlash(&(interface->io[0].b))) : tffsReadWordFlash(&(interface->io[0].w))) ;
chipId_p = (vol.interleaving == 1 ? DBL(tffsReadByteFlash(&(interface->io[0].b))) : tffsReadWordFlash(&(interface->io[0].w)));
tffsWriteWordFlash(&(interface->signals.w), DBL(NOT_WP));
if ( isKnownMedia_nfdc2048(&vol, vendorId_p, chipId_p, dev) != TRUE ) /* no chip or diff.*/
return FALSE ; /* type of flash */
/* set flash parameters*/
if ( dev == 0 )
{
thisVars->pageAreaSize = (USHORT) (0x100 * vol.interleaving);
thisVars->pageSize = (USHORT) ((vol.flags & BIG_PAGE ? 0x200 : 0x100) * vol.interleaving);
thisVars->tailSize = (USHORT) ((vol.flags & BIG_PAGE ? 16 : 8) * vol.interleaving);
thisVars->pageMask = thisVars->pageSize - 1 ;
vol.erasableBlockSize = thisVars->pagesPerBlock * thisVars->pageSize;
thisVars->noOfBlocks = (USHORT)( (vol.chipSize * vol.interleaving)
/ vol.erasableBlockSize ) ;
}
return TRUE ;
}
/*----------------------------------------------------------------------*/
/* c d s n I d e n t i f y */
/* */
/* Identify flash. This routine will be registered as the */
/* identification routine for this MTD. */
/* */
/* Returns: */
/* FLStatus: 0 on success, otherwise failed. */
/* */
/*----------------------------------------------------------------------*/
FLStatus cdsnIdentify(FLFlash vol)
{
LONG addr = 0L ;
Interface interface;
DEBUG_PRINT(("Debug: Entering NFDC 2048 identification routine\n"));
flDelayMsecs(10); /* wait for socket to power up */
flSetWindowBusWidth(vol.socket,16);/* use 16-bits */
flSetWindowSpeed(vol.socket,250); /* 250 nsec. */
flSetWindowSize(vol.socket,2); /* 4 KBytes */
vol.mtdVars = &mtdVars_nfdc2048[flSocketNoOf(vol.socket)];
/* get pointer to buffer (we assume SINGLE_BUFFER is not defined) */
thisVars->buffer = flBufferOf(flSocketNoOf(vol.socket));
/* detect card - identify bit toggles on consequitive reads*/
vol.chipSize = 0x200000L ; /* Assume something ... */
vol.interleaving = 1; /* unimportant for now */
interface = mapContInterface(&vol, 0);
KeStallExecutionProcessor(250 * 1000);
if((tffsReadByteFlash(&(interface->eccConfig.b)) & TOGGLE) == (tffsReadByteFlash(&(interface->eccConfig.b)) & TOGGLE))
return flUnknownMedia;
/* read interleave from the card*/
#ifdef NFDC2048
vol.interleaving = ( (getAttReg(&vol, JUMPERS ) & JMPER_INLV) ? 1 : 2 );
powerUp((VOID *) &vol);
interface = mapContInterface(&vol, 0);
KeStallExecutionProcessor(250 * 1000);
if (vol.interleaving == 1)
flSetWindowBusWidth(vol.socket, 8);
#else
vol.interleaving = INLV;
#endif /* NFDC2048 */
/* reset all flash devices*/
tffsWriteWordFlash(&(interface->signals.w), DBL(NOT_WP));
/* identify and count flash chips, figure out flash parameters*/
for (vol.noOfChips = 0 ;
vol.noOfChips < MAX_FLASH_DEVICES;
vol.noOfChips += vol.interleaving,
addr += vol.chipSize * vol.interleaving)
{
interface = mapContInterface(&vol, addr) ;
if ( readFlashID2048(&vol, interface, vol.noOfChips) != TRUE ) /* no chip or different type of flash*/
break ;
}
if ( vol.noOfChips == 0 ) /* no chips were found */
return flUnknownMedia;
/* ECC off*/
interface = mapContInterface(&vol, 0);
KeStallExecutionProcessor(250 * 1000);
#ifdef NFDC2048
SET_ECC_CONFIG(interface, PAR_DIS); /* disable ECC and parity*/
setAttReg(&vol, CARD_CONFIG, PWRDWN);
#endif /* NFDC2048 */
/* Register our flash handlers */
vol.write = cdsnWrite;
vol.erase = cdsnErase;
vol.read = cdsnRead;
vol.map = cdsnMap;
#ifdef NFDC2048
vol.setPowerOnCallback = cdsnSetCallback;
#endif
vol.flags |= NFTL_ENABLED;
DEBUG_PRINT(("Debug: Identified NFDC 2048.\n"));
return flOK;
}
/*----------------------------------------------------------------------*/
/* f l R e g i s t e r C D S N */
/* */
/* Registers this MTD for use */
/* */
/* Parameters: */
/* None */
/* */
/* Returns: */
/* FLStatus : 0 on success, otherwise failure */
/*----------------------------------------------------------------------*/
FLStatus flRegisterCDSN(VOID)
{
if (noOfMTDs >= MTDS)
return flTooManyComponents;
mtdTable[noOfMTDs++] = cdsnIdentify;
return flOK;
}