cfiscs.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:47k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* cfiscs.c - MTD for devices that comply with CFI and the Intel SCS */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /* FAT-FTL Lite Software Development Kit
  5.  * Copyright (C) M-Systems Ltd. 1995-2001       */
  6. /*
  7. modification history
  8. --------------------
  9. 01h,24jun02,nrv  fixing the condition where flashPtr[0x24] is checked twice
  10. 01g,12dec01,yp   removing assumption that the InterleavedWordWrite call might
  11.                  have to support 16 bit commands. reworked identification of
  12.                  two 16 bit devices and single 32 bit device. made erase
  13.                  routines mutually exclusive at compile time. removed dataWidth
  14.  and deviceWidth members from CFI structure. removed unused 
  15.  MakeCmd function.
  16. 01f,11dec01,nrv  fixed build error
  17. 01e,29oct01,yp   Converting to WRS coding convention. Adding support for double
  18.  word width devices. Converting identification process to byte 
  19.  offsets. Providing alternative write mechanism for none 
  20.  functional WRITE_TO_BUFFER paltforms.
  21. 01d,.......,vf   Added for debugging of this MTD.
  22. 01c,06apr99,vf   Try to make endian-safe.  LONGSWAP and WORDSWAP are 
  23.  #define'd in vxWorks.h.
  24. 01b,09jan99,an   Added support for machines that require a full 32bit write to 
  25.  access fall correctly. Also fixed code to correctly compute 
  26.  total Flash size, virtual block size, and combined write buffer
  27.  size when interleaved parts are detected.
  28. 01a,27may97,msys original version from M-Systems
  29. */
  30. /* Original CVS history
  31.  * $Log: cfiscs.c,v $
  32.  * Revision 1.1  2000/07/13 01:46:37  caluml
  33.  * Added TFFS and bootParams stuff
  34.  *
  35.  * Revision 1.1.1.1  2000/05/31 00:09:33  caluml
  36.  * T201 Arm Ugl2
  37.  *
  38.  * Revision 1.1  2000/04/14 16:26:14  caluml
  39.  * This version is for the Assabet board with 32Mb of StrataFlash memory
  40.  *
  41.  *
  42.  *    Rev 1.20   11 Nov 1997 15:26:00   ANDRY
  43.  * get rid of compiler warnings
  44.  *
  45.  *    Rev 1.19   06 Oct 1997  9:53:30   danig
  46.  * VPP functions under #ifdef
  47.  *
  48.  *    Rev 1.18   18 Sep 1997 10:05:40   danig
  49.  * Warnings
  50.  *
  51.  *    Rev 1.17   10 Sep 1997 16:31:16   danig
  52.  * Got rid of generic names
  53.  *
  54.  *    Rev 1.16   04 Sep 1997 18:19:34   danig
  55.  * Debug messages
  56.  *
  57.  *    Rev 1.15   31 Aug 1997 14:50:52   danig
  58.  * Registration routine return status
  59.  *
  60.  *    Rev 1.14   27 Jul 1997 15:00:38   danig
  61.  * FAR -> FAR0
  62.  *
  63.  *    Rev 1.13   21 Jul 1997 19:58:24   danig
  64.  * No watchDogTimer
  65.  *
  66.  *    Rev 1.12   15 Jul 1997 19:18:32   danig
  67.  * Ver 2.0
  68.  *
  69.  *    Rev 1.11   09 Jul 1997 10:58:52   danig
  70.  * Fixed byte erase bug & changed identification routines
  71.  *
  72.  *    Rev 1.10   20 May 1997 14:48:02   danig
  73.  * Changed overwrite to mode in write routines
  74.  *
  75.  *    Rev 1.9   18 May 1997 13:54:58   danig
  76.  * JEDEC ID independent
  77.  *
  78.  *    Rev 1.8   13 May 1997 16:43:10   danig
  79.  * Added getMultiplier.
  80.  *
  81.  *    Rev 1.7   08 May 1997 19:56:12   danig
  82.  * Added cfiscsByteSize
  83.  *
  84.  *    Rev 1.6   04 May 1997 14:01:16   danig
  85.  * Changed cfiscsByteErase and added multiplier
  86.  *
  87.  *    Rev 1.4   15 Apr 1997 11:38:52   danig
  88.  * Changed word identification and IDs.
  89.  *
  90.  *    Rev 1.3   15 Jan 1997 18:21:40   danig
  91.  * Bigger ID string buffers and removed unused definitions.
  92.  *
  93.  *    Rev 1.2   08 Jan 1997 14:54:06   danig
  94.  * Changes in specification
  95.  *
  96.  *    Rev 1.1   25 Dec 1996 18:21:44   danig
  97.  * Initial revision
  98.  */
  99. /*
  100. DESCRIPTION
  101. This library provides an MTD for devices that conform to the Common Flash 
  102. Interface (CFI) and the Intel Scalable Command Set (SCS). The library provides 
  103. identification, erase and write routines for 8, 16, and 32 bit devices in 
  104. native or byte mode. Support is also added for word width devices 
  105. interleaved in word width mode where bytes 0 and 1 would be on device one 
  106. and bytes 2 and 3 would be on device two. Support is also present for 
  107. configurations thatonly permit double word width writes.
  108. The identification process supports byte, word, and double word width devices 
  109. as specified by the CFI query process. Vendr specific extentions are made 
  110. available from an instance specific data structure, referred to in this file 
  111. as thisCFI. However, the driver remains vendor nutral in the hope that it 
  112. will be applicable to a larger range of devices.
  113. In addition to supporting a boot code region this driver is also able to 
  114. reserve the last erase block of each device in the array so the vxWorks may
  115. use this region as NVRAM if the macro SAVE_NVRAM_REGION is defined.
  116. Some hardware using word width interleaved devices permit only 32 bit writes.
  117. In these environments the macro INTERLEAVED_MODE_REQUIRES_32BIT_WRITES must 
  118. be defined. The erase routine in particular and some of the write routines are 
  119. impacted by this. 
  120. BSPs tested:
  121. BSP Device Socket Defines
  122. Assabet StrataFlash RFA 32_BIT_WRITES
  123. SAVE_NVRAM
  124. ddb5476 StrataFlash RFA
  125. pcPentum3 StrataFlash PCMCIA
  126. ads860 StrataFlash PCMCIA
  127. prpm800 StrataFlash RFA BUFFER_WRITE_BROKEN
  128. integrator StrataFlash RFA SAVE_NVRAM
  129. (720/920)
  130. NOMANUAL
  131. */
  132. #include <stdio.h>
  133. #include "tffs/flflash.h"
  134. #include "tffs/backgrnd.h"
  135. /* Instance specific CFI data so that a system may have more than one CFI
  136.  * device. */
  137. typedef struct {
  138.   unsigned         commandSetId;            /* id of a specific command set. */
  139.   unsigned         altCommandSetId;         /* id of alternate command set.  */
  140.   FLBoolean        wordMode;                /* TRUE - word mode.             */
  141.     /* FALSE - byte mode.            */
  142.   int              multiplier;              /* the number of bytes in       */
  143.     /* addressing scheme      */
  144.   int    interleaveFactor;     /* Number of bytes interleaved   */
  145.   unsigned         maxBytesWrite;           /* maximum number of bytes       */
  146.     /* in multi-byte write.          */
  147.   FLBoolean        vpp;                     /* if = TRUE, need vpp.          */
  148.   long             optionalCommands;        /* optional commands supported   */
  149.     /* (1 = yes, 0 = no):            */
  150.     /* bit 0 - chip erase.           */
  151.     /* bit 1 - suspend erase.        */
  152.     /* bit 2 - suspend write         */
  153.     /* bit 3 - lock/unlock.          */
  154.     /* bit 4 - queued erase.         */
  155.   unsigned         afterSuspend;            /* functions supported after     */
  156.     /* suspend (1 = yes, 0 = no):    */
  157.     /* bit 0 - write after erase     */
  158.     /*         suspend.              */
  159. } CFI;
  160. LOCAL CFI mtdVars[DRIVES];
  161. /* defines */
  162. /* 
  163.  * define the following if the target requires interleaves to be 
  164.  * full 32 bit write accesses when erasing blocks. The Assabet BSP
  165.  * is the onlyone requiring this so far.
  166.  */
  167. #undef INTERLEAVED_MODE_REQUIRES_32BIT_WRITES
  168. /* Save the last erase block on each device discovered in the array 
  169.  * for NVRAM */
  170. #define SAVE_NVRAM_REGION
  171. /* disable debugging */
  172. #define CFI_DEBUG
  173. #ifdef CFI_DEBUG
  174. #define DEBUG_PRINT    printf
  175. #else
  176. #undef DEBUG_PRINT
  177. #endif
  178. /* define the following if the WRITE_TO_BUFFER command does not work
  179.  * The value of maxBytesWrite is then forced to 1, resulting in either 
  180.  * byte or word writes being used
  181.  */
  182. #undef  BUFFERED_WRITE_BROKEN
  183. #ifndef _BYTE_ORDER
  184. #error "Error: _BYTE_ORDER needs to be #define'd.  Try #include "vxWorks.h" "
  185. #endif
  186. #if (_BYTE_ORDER == _BIG_ENDIAN)
  187. #define CFI_LONGSWAP(x) LONGSWAP(x) /* swap everything in a long word */
  188. #define CFI_WORDSWAP(x) WORDSWAP(x) /* swap the shorts in a long */
  189. #define CFI_BYTESWAP(x) ( ( (x & 0xff) << 8) | ( (x >> 8) & 0xff) )  /* Swap bytes in a short */
  190. #else
  191. #define CFI_LONGSWAP(x) (x) /* pass it as is */
  192. #define CFI_WORDSWAP(x) (x) /* pass it as is */
  193. #define CFI_BYTESWAP(x) (x) /* pass it as is */
  194. #endif /* _BYTE_ORDER == _BIG_ENDIAN */
  195. #define CFI_LONG_WRITE(addr, data)  (*(ULONG *)addr = (ULONG)(CFI_LONGSWAP(data)))
  196. #define CFI_WORD_WRITE(addr, data)  (*(USHORT *)addr = (USHORT)(CFI_WORDSWAP(data)))
  197. #define CFI_WORD_READ(addr)         (CFI_BYTESWAP(*(USHORT *)addr))
  198. #define CFI_LONG_READ(addr)         (CFI_WORDSWAP(*(ULONG *)addr))
  199. /* JEDEC-IDs */
  200. #define VOYAGER_ID              0x8915
  201. #define KING_COBRA_ID           0xb0d0
  202. /* command set IDs */
  203. #define INTEL_COMMAND_SET      0x0001
  204. #define AMDFUJ_COMMAND_SET     0x0002
  205. #define INTEL_ALT_COMMAND_SET  0x0001
  206. #define AMDFUJ_ALT_COMMAND_SET 0x0004
  207. #define ALT_NOT_SUPPORTED      0x0000
  208. /* CFI identification strings */
  209. #define ID_STR_LENGTH      3
  210. #define QUERY_ID_STR       "QRY"
  211. #define PRIMARY_ID_STR     "PRI"
  212. #define ALTERNATE_ID_STR   "ALT"
  213. /* commands */
  214. #define CONFIRM_SET_LOCK_BIT    0x01
  215. #define PROGRAM_WORD            0x10
  216. #define SETUP_BLOCK_ERASE       0x20
  217. #define SETUP_QUEUE_ERASE       0x28
  218. #define SETUP_CHIP_ERASE        0x30
  219. #define PROGRAM                 0x40
  220. #define CLEAR_STATUS            0x50
  221. #define SET_LOCK_BIT            0x60
  222. #define CLEAR_LOCK_BIT          0x60
  223. #define READ_STATUS             0x70
  224. #define READ_ID                 0x90
  225. #define QUERY                   0x98
  226. #define SUSPEND_WRITE           0xb0
  227. #define SUSPEND_ERASE           0xb0
  228. #define CONFIG                  0xb8
  229. #define CONFIRM_WRITE           0xd0
  230. #define RESUME_WRITE            0xd0
  231. #define CONFIRM_ERASE           0xd0
  232. #define RESUME_ERASE            0xd0
  233. #define CONFIRM_CLEAR_LOCK_BIT  0xd0
  234. #define WRITE_TO_BUFFER         0xe8
  235. #define READ_ARRAY              0xff
  236. /* status register bits */
  237. #define WSM_ERROR               0x3a
  238. #define SR_BLOCK_LOCK           0x02
  239. #define SR_WRITE_SUSPEND        0x04
  240. #define SR_VPP_ERROR            0x08
  241. #define SR_WRITE_ERROR          0x10
  242. #define SR_LOCK_SET_ERROR       0x10
  243. #define SR_ERASE_ERROR          0x20
  244. #define SR_LOCK_RESET_ERROR     0x20
  245. #define SR_ERASE_SUSPEND        0x40
  246. #define SR_READY                0x80
  247. /* optional commands support */
  248. #define CHIP_ERASE_SUPPORT           0x0001
  249. #define SUSPEND_ERASE_SUPPORT        0x0002
  250. #define SUSPEND_WRITE_SUPPORT        0x0004
  251. #define LOCK_SUPPORT                 0x0008
  252. #define QUEUED_ERASE_SUPPORT         0x0010
  253. /* supported functions after suspend */
  254. #define WRITE_AFTER_SUSPEND_SUPPORT  0x0001
  255. #define thisCFI   ((CFI *)vol.mtdVars)
  256. /******************************************************************************
  257.  * cfiscsGetChipCount - return the number of chips in this array
  258.  *
  259.  * Leave the first chip (or set of interleaved chips) in READ_ARRAY
  260.  * mode and move forward by chip size (or interleaved chip size) until
  261.  * address wrap around is detected. The chip count is updated in 
  262.  * vol.noOfChips.
  263.  *
  264.  * NOMANUAL
  265.  *
  266.  */
  267. LOCAL FLStatus cfiscsGetChipCount
  268.     (
  269.     FLFlash vol
  270.     )
  271.     {
  272.     UINT32 cmdBuffer;
  273.     int ix;
  274.     char queryIdStr[ID_STR_LENGTH + 1] = QUERY_ID_STR;
  275.     FlashPTR flashPtr = (FlashPTR) flMap(vol.socket, 0);
  276.     /* Switch first (interleaved) chip set to QUERY mode */
  277.     cmdBuffer = 0x0;
  278.     for (ix = 0; ix < thisCFI->multiplier; ix++)
  279. cmdBuffer |= QUERY << (8 * ix);
  280.     flashPtr[0x55 * thisCFI->multiplier] = cmdBuffer;
  281.     /* NOTE: The address wrap around technique used here works only if the flash
  282.      * size was declared correctly in the socket driver. At some point the MTD
  283.      * should be discovering flash size and exporting it to the socket driver. 
  284.      */
  285.     for (vol.noOfChips = 1 * vol.interleaving;       /* Scan the chips */
  286.          vol.noOfChips < 2000;  /* Big enough ? */
  287.          vol.noOfChips += vol.interleaving) 
  288.         {
  289. #ifdef SAVE_NVRAM_REGION
  290. /* Reinstate the NVRAM region */
  291. flashPtr = (FlashPTR) flMap(vol.socket, vol.noOfChips * 
  292. (vol.chipSize + (vol.erasableBlockSize / vol.interleaving)));
  293. #else
  294. flashPtr = (FlashPTR) flMap(vol.socket, vol.noOfChips * vol.chipSize);
  295. #endif
  296. #ifdef DEBUG_PRINT
  297. DEBUG_PRINT("Debug: Looking for Flash device at base 0x%xn", (UINT32) flashPtr);
  298. #endif
  299. if ((flashPtr[0x10 * thisCFI->multiplier]) 
  300.     == (unsigned char)queryIdStr[0] &&
  301.     (flashPtr[0x11 * thisCFI->multiplier]) 
  302.     == (unsigned char)queryIdStr[1] &&
  303.     (flashPtr[0x12 * thisCFI->multiplier]) 
  304.     == (unsigned char)queryIdStr[2])
  305.     {
  306.     goto noMoreChips;      /* Wrapped around */
  307.     }
  308. /* Confirm this is also a CFI part */
  309. *(UCHAR *)(flashPtr + (0x55 * thisCFI->multiplier))
  310.    = (UCHAR)(QUERY);
  311. if (flashPtr[0x10 * thisCFI->multiplier]
  312. != (unsigned char)queryIdStr[0] ||
  313.     flashPtr[0x11 * thisCFI->multiplier]
  314. != (unsigned char)queryIdStr[1] ||
  315.     flashPtr[0x12 * thisCFI->multiplier]
  316. != (unsigned char)queryIdStr[2])
  317.     {
  318.     /* Should not happen !! */
  319.     goto noMoreChips; /* Not a CFI Flash part */
  320.     }
  321. flashPtr[0x55 * thisCFI->multiplier] 
  322. = (UCHAR)(CLEAR_STATUS);
  323. flashPtr[0x55 * thisCFI->multiplier] 
  324. = (UCHAR)(READ_ARRAY);
  325. }
  326.     /* We should never get here. */
  327. #ifdef DEBUG_PRINT
  328.     DEBUG_PRINT("Debug: Device count overflown");
  329. #endif  /* DEBUG_PRINT */
  330.     return flGeneralFailure;
  331.     
  332. noMoreChips:
  333.     flashPtr = (FlashPTR) flMap(vol.socket, 0);
  334.     /* Switch to READ_ARRAY mode */
  335.     cmdBuffer = 0x0;
  336.     for (ix = 0; ix < thisCFI->multiplier; ix++)
  337. cmdBuffer |= READ_ARRAY << (8 * ix);
  338.     flashPtr[0x55 * thisCFI->multiplier] = cmdBuffer;
  339.     return flOK;
  340.     }
  341. /******************************************************************************
  342.  * cfiscsByteWrite - byte write routine
  343.  *
  344.  * This routine is intended to be registered as the write routine in systems
  345.  * that have byte wide devices interleaved or devices that are in byte mode.
  346.  *
  347.  * NOMANUAL
  348.  *
  349.  */
  350. LOCAL FLStatus cfiscsByteWrite
  351.     (
  352.     FLFlash vol,
  353.     CardAddress address,
  354.     const void FAR1 *buffer,
  355.     int length,
  356.     int mode
  357.     )
  358.     {
  359.     FLStatus status = flOK;
  360.     FlashPTR flashPtr;
  361.     unsigned int i, from, eachWrite;
  362.     const char FAR1 *temp = (const char FAR1 *)buffer;
  363.     /* Set timeout to 5 seconds from now */
  364.     unsigned long writeTimeout = flMsecCounter + 5000;
  365.     if (flWriteProtected(vol.socket))
  366. return flWriteProtect;
  367. #ifdef SOCKET_12_VOLTS
  368.     if (thisCFI->vpp)
  369. checkStatus(flNeedVpp(vol.socket));
  370. #endif
  371.     if (thisCFI->maxBytesWrite > 1) /* multi-byte write supported */
  372. eachWrite = thisCFI->maxBytesWrite * vol.interleaving;
  373.     else
  374. eachWrite = vol.interleaving;
  375.     for (from = 0; (int)from < length && status == flOK; from += eachWrite) 
  376. {
  377. int thisLength = length - from;
  378. FlashPTR currPtr;
  379. unsigned tailBytes, lengthByte;
  380. if (thisLength > (int)eachWrite)
  381.     thisLength = eachWrite;
  382. lengthByte = thisLength / vol.interleaving;
  383. tailBytes = thisLength % vol.interleaving;
  384. flashPtr = (FlashPTR) flMap(vol.socket, address + from);
  385. for (i = 0, currPtr = flashPtr;
  386.     ((int)i < vol.interleaving) && ((int)i < thisLength);
  387.     i++, currPtr++) 
  388.     {
  389.     do 
  390. {
  391. *currPtr = WRITE_TO_BUFFER;
  392. } while (!(*currPtr & SR_READY) && 
  393. (flMsecCounter < writeTimeout));
  394.     if (!(*currPtr & SR_READY)) 
  395. {
  396. #ifdef DEBUG_PRINT
  397. DEBUG_PRINT("Debug: timeout error in CFISCS write.n");
  398. #endif
  399. status = flWriteFault;
  400. }
  401.     *currPtr = i < tailBytes ? lengthByte : lengthByte - 1;
  402.     }
  403. tffscpy((unsigned long FAR0 *) flashPtr,temp + from,thisLength);
  404. for (i = 0, currPtr = flashPtr;
  405. ((int)i < vol.interleaving) && ((int)i < thisLength);
  406. i++, currPtr++)
  407.     *currPtr = CONFIRM_WRITE;
  408. for (i = 0, currPtr = flashPtr;
  409. ((int)i < vol.interleaving) && ((int)i < thisLength);
  410. i++, currPtr++) 
  411.     {
  412.     while (!(*currPtr & SR_READY) && (flMsecCounter < writeTimeout))
  413. ;
  414.     if (!(*currPtr & SR_READY)) 
  415. {
  416. #ifdef DEBUG_PRINT
  417. DEBUG_PRINT("Debug: timeout error in CFISCS write.n");
  418. #endif
  419. status = flWriteFault;
  420. }
  421.     if (*currPtr & WSM_ERROR) 
  422. {
  423. #ifdef DEBUG_PRINT
  424. DEBUG_PRINT("Debug: error in CFISCS write.n");
  425. #endif
  426. status = (*currPtr & SR_VPP_ERROR) ? 
  427.     flVppFailure : flWriteFault;
  428. *currPtr = CLEAR_STATUS;
  429. }
  430.     *currPtr = READ_ARRAY;
  431.     }
  432. }
  433. #ifdef SOCKET_12_VOLTS
  434.     if (thisCFI->vpp)
  435.      flDontNeedVpp(vol.socket);
  436. #endif
  437.     flashPtr = (FlashPTR) flMap(vol.socket, address);
  438.     /* verify the data */
  439.     if (status == flOK && tffscmp((void FAR0 *) flashPtr,buffer,length)) 
  440.      {
  441. #ifdef DEBUG_PRINT
  442.      DEBUG_PRINT("Debug: CFISCS write failed in verification.n");
  443. #endif
  444.      status = flWriteFault;
  445.      }
  446.     return status;
  447.     }
  448. /*****************************************************************************
  449.  * cfiscsWordWrite - write routine for 16 bit devices 
  450.  *                                                                     
  451.  * Write a block of bytes to Flash in a word-mode.                    
  452.  *                                                                   
  453.  * This routine will be registered as the MTD flash.write routine   
  454.  *                                                                 
  455.  * Parameters:                                                    
  456.  *      vol             : Pointer identifying drive              
  457.  *      address         : Card address to write to              
  458.  *      buffer          : Address of data to write             
  459.  *      length          : Number of bytes to write            
  460.  *      mode            : write mode (overwrite yes/no)      
  461.  *                                                          
  462.  * Returns:                                                
  463.  *      FLStatus        : 0 on success, failed otherwise  
  464.  *
  465.  * NOMANUAL
  466.  *
  467.  */
  468. LOCAL FLStatus cfiscsWordWrite
  469.     (
  470.     FLFlash vol,
  471.     CardAddress address,
  472.     const void FAR1 *buffer,
  473.     int length,
  474.     int mode
  475.     )
  476.     {
  477.     FLStatus status = flOK;
  478.     FlashWPTR flashPtr;
  479.     int from, eachWrite;
  480.     const char FAR1 *temp = (const char FAR1 *)buffer;
  481.     /* Set timeout to 5 seconds from now */
  482.     unsigned long writeTimeout = flMsecCounter + 5000;
  483.     if (flWriteProtected(vol.socket))
  484. return flWriteProtect;
  485.     if ((length & 1) || (address & 1)) /* Only write words on word-boundary */
  486. return flBadParameter;
  487. #ifdef SOCKET_12_VOLTS
  488.     if (thisCFI->vpp)
  489. checkStatus(flNeedVpp(vol.socket));
  490. #endif
  491.     if (thisCFI->maxBytesWrite > 1) /* multi-byte write supported */
  492. eachWrite = thisCFI->maxBytesWrite / 2;   /* we are counting words */
  493.     else
  494. eachWrite = 1;
  495.     /* we assume that the interleaving is 1. */
  496.     for (from = 0; (from < length / 2) && (status == flOK); from += eachWrite) 
  497. {
  498. int thisLength = (length / 2) - from;
  499. if (thisLength > eachWrite)
  500.     thisLength = eachWrite;
  501. flashPtr = (FlashWPTR)flMap(vol.socket, address + from * 2);
  502. if (thisLength == 1) 
  503.     {
  504.     *flashPtr = PROGRAM ;
  505.     *flashPtr = * ( (FlashWPTR) (temp + from * 2) ) ;
  506.     } 
  507. else 
  508.     {
  509.     /* count > 1 so do a multiple write */
  510.     do 
  511. {
  512. *flashPtr = WRITE_TO_BUFFER;
  513. } while (!(*flashPtr & SR_READY) && (flMsecCounter < writeTimeout));
  514.     if (!(*flashPtr & SR_READY)) 
  515. {
  516. #ifdef DEBUG_PRINT
  517. DEBUG_PRINT("Debug: timeout error in CFISCS write.n");
  518. #endif
  519. status = flWriteFault;
  520. }
  521.     *flashPtr = thisLength - 1;
  522.     tffscpyWords((unsigned long FAR0 *) flashPtr, temp + from * 2, thisLength * 2);
  523.     *flashPtr = CONFIRM_WRITE;
  524.     }
  525. while (!(*flashPtr & SR_READY) && (flMsecCounter < writeTimeout))
  526.       ;
  527. if (!(*flashPtr & SR_READY)) 
  528.     {
  529. #ifdef DEBUG_PRINT
  530.     DEBUG_PRINT("Debug: timeout error in CFISCS write.n");
  531. #endif
  532.     status = flWriteFault;
  533.     }
  534. if (*flashPtr & WSM_ERROR) 
  535.     {
  536. #ifdef DEBUG_PRINT
  537.     DEBUG_PRINT("Debug: CFISCS write error.n");
  538. #endif
  539.     status = (*flashPtr & SR_VPP_ERROR) ? flVppFailure : flWriteFault;
  540.     *flashPtr = CLEAR_STATUS;
  541.     }
  542. *flashPtr = READ_ARRAY;
  543.         }
  544. #ifdef SOCKET_12_VOLTS
  545.     if (thisCFI->vpp)
  546. flDontNeedVpp(vol.socket);
  547. #endif
  548.     flashPtr = (FlashWPTR) flMap(vol.socket, address);
  549.     /* verify the data */
  550.     if (status == flOK && tffscmp((void FAR0 *) flashPtr,buffer,length)) 
  551. {
  552. #ifdef DEBUG_PRINT
  553. DEBUG_PRINT("Debug: CFISCS write failed in verification.n");
  554. #endif
  555. status = flWriteFault;
  556. }
  557.     return status;
  558.     }
  559. /******************************************************************************
  560.  * cfiscsInterleavedWordWrite - write routine 16 bit interleaved devices
  561.  *                                                                 
  562.  * This routine will be registered as the MTD flash.write routine      
  563.  *                                                                    
  564.  * Parameters:                                                       
  565.  *      vol             : Pointer identifying drive                 
  566.  *      address         : Card address to write to                 
  567.  *      buffer          : Address of data to write                
  568.  *      length          : Number of bytes to write               
  569.  *      mode            : write mode (overwrite yes/no)         
  570.  *                                                             
  571.  * Returns:                                                   
  572.  *      FLStatus        : 0 on success, failed otherwise     
  573.  *
  574.  * NOMANUAL
  575.  *
  576.  */
  577. LOCAL FLStatus cfiscsInterleavedWordWrite
  578.     (
  579.     FLFlash vol,
  580.     CardAddress address,
  581.     const void FAR1 *buffer,
  582.     int length,
  583.     int mode
  584.     )
  585.     {
  586.     FLStatus status = flOK;
  587.     FlashWPTR flashPtr;
  588.     unsigned long maxWordsPerWrite,  /* Number of words per WRITE/WRITE_BUFFER 
  589. command. */
  590.                 wordsWritten,      /* total written so far */
  591.                 wordsRemaining,    /* number of words left to go */
  592.                 wordsThisWrite;    /* number of words */
  593.  
  594.     if (flWriteProtected(vol.socket))
  595. return flWriteProtect;
  596.     if ((length & 1) || (address & 1))  /* Only write whole words, 
  597.    only on word-boundary */
  598. return flBadParameter;
  599. #ifdef SOCKET_12_VOLTS
  600.     if (thisCFI->vpp)
  601. checkStatus(flNeedVpp(vol.socket));
  602. #endif
  603.     if (thisCFI->maxBytesWrite > 1) /* multi-byte write supported? */
  604.         maxWordsPerWrite = thisCFI->maxBytesWrite;
  605.     else
  606. maxWordsPerWrite = 1;  /* Part can only handle single-byte writes. */
  607.     flashPtr = (FlashWPTR)flMap(vol.socket, address);
  608.     /* Now program the part: */
  609.     if (maxWordsPerWrite > 1)  /* Part can handle writes of multiple 
  610.   words to buffer */
  611. {
  612.         wordsWritten = 0;
  613.         wordsRemaining = length / 2;  /* Number of words left to program into 
  614.  a part, convert bytes to words. */
  615.         while (wordsRemaining > 0)
  616.     {
  617.     /* Figure out how many words we need to write.  This will either 
  618.      * be the max allowed (maxWordsPerWrite), or what's left over at 
  619.      * the end (wordsRemaining).  Make it extra-cryptic with the
  620.      * ?: operator.
  621.      */
  622.      wordsThisWrite = (wordsRemaining > maxWordsPerWrite) 
  623.  ? maxWordsPerWrite : wordsRemaining;
  624.   
  625.     /* if we dont have enough aligned data to use a buffered write 
  626.      * we just use a normal write */
  627.     if ( (wordsThisWrite <2 ) && (wordsThisWrite > 0))
  628. {
  629. /* data is a 1's mask, so we only try overwriting the 
  630.  * bytes we desire ie. written a 1 should not change 
  631.  * the state of an erase bit */
  632. int byteCount;
  633.         ULONG data = 0xffffffff; 
  634.         /* clear out the bytes we are going to overwrite */
  635. for(byteCount = 0; byteCount<length; byteCount++)
  636.     data &= ~(0xff << (byteCount*8));
  637. /* set the bits we dont want to clear in our data */
  638. data |= CFI_LONGSWAP(* (ULONG *) buffer);
  639. CFI_LONG_WRITE(flashPtr, (ULONG) (PROGRAM<<16) |PROGRAM);
  640. CFI_LONG_WRITE(flashPtr, (ULONG) data);
  641. /* Flow diagram says to check that status register says 
  642.  * everything is copacetic. */
  643. while ( (!(CFI_WORD_READ(flashPtr) & SR_READY)) ||
  644.       (!(CFI_WORD_READ((flashPtr + 1)) & SR_READY)) );  
  645. CFI_LONG_WRITE(flashPtr, (ULONG) (READ_ARRAY<<16) |READ_ARRAY); 
  646. #ifdef DEBUG_PRINT
  647.   DEBUG_PRINT("Debug: mtd: Using NON-buffered write to program %ld words at addr 0x%lxn", 
  648.       wordsThisWrite, (ULONG) flashPtr);
  649. #endif
  650. }
  651.     else
  652. {
  653.                 CFI_LONG_WRITE(flashPtr, (ULONG) ((CLEAR_STATUS<<16)
  654.                         |CLEAR_STATUS));
  655. CFI_LONG_WRITE(flashPtr, (ULONG) (WRITE_TO_BUFFER<<16) 
  656. |WRITE_TO_BUFFER);  /* both parts */
  657.       
  658. /* At this point, we must wait for XSR to indicate a buffer is 
  659.  * available. We will spin on this, but only for a maximum of 5 
  660.  * seconds.  We do the timing by taking advantage of the 
  661.  * ever-incrementing flMsecCounter.
  662.  */
  663.  while ((!(CFI_WORD_READ((FlashWPTR)(flashPtr)) & SR_READY)) ||
  664.       (!(CFI_WORD_READ((FlashWPTR)(flashPtr + 1)) & SR_READY)))
  665.      ;
  666.       
  667.  /* Check to see if either part timed out: */
  668.  if ( (!(CFI_WORD_READ(&flashPtr[0x0])     & SR_READY)) ||
  669.     (!(CFI_WORD_READ((&flashPtr[0x1])) & SR_READY)) )
  670.     {
  671.     /* Send read-array command to both parts, abort. */
  672.     CFI_LONG_WRITE(flashPtr, (ULONG) (READ_ARRAY<<16) |READ_ARRAY);
  673.     return(flWriteFault);
  674.     }
  675.       
  676.  /* Now we must write the count value (zero-based, so 0 => 1 word,
  677.   * 1 => 2 words, etc.) for the number of words we intend to 
  678.   * write.  Note that this code always assumes an even number of 
  679.   * words > 0.  Half the words go in the even part, half go in the 
  680.   * odd part.
  681.   */
  682.   CFI_LONG_WRITE(flashPtr, (ULONG)(((wordsThisWrite / 2)  - 1)
  683.   <<16) | ((wordsThisWrite / 2) - 1));  /* both parts */
  684.       
  685.   /* Finally, write the data.  This is easy, because now the 
  686.    * flash parts are seen as memory addresses.
  687.    */
  688.   /* FIXME: This is suboptimal.  It is only writing half the 
  689.    * maximum words that could be written to each part in buffered 
  690.    * write mode. If we double the assignments for wordsWritten & 
  691.    * wordsThisWrite, and halve the assignment for wordsRemaining 
  692.    * each iteration, we can probably make this work optimally.
  693.    * Then we should probably rename some of the variables to 
  694.    * "longsxxx".
  695.    */
  696.   /* last arguement is expected in bytes */
  697.   tffscpyLongs(&((long *)flashPtr)[wordsWritten/2], 
  698.   &((long *)buffer)[wordsWritten/2], wordsThisWrite*2);
  699.       
  700.   /* Now send CONFIRM_WRITE command. */
  701.   CFI_LONG_WRITE(flashPtr, (ULONG) (CONFIRM_WRITE<<16) 
  702.     | CONFIRM_WRITE);  /* both parts */
  703.   /* Flow diagram says to check that status register says 
  704.    * everything is copacetic. */
  705.   while ( (!(CFI_WORD_READ(flashPtr)     & SR_READY)) ||
  706. (!(CFI_WORD_READ((flashPtr + 1)) & SR_READY)) ); 
  707.   
  708.   /* Check to see if either part timed out: */
  709.   if ( (!(CFI_WORD_READ(flashPtr)     & SR_READY)) ||
  710.      (!(CFI_WORD_READ((flashPtr + 1)) & SR_READY)) )
  711.      {
  712.      /* Send read-array command to both parts, abort. */
  713.      CFI_LONG_WRITE(flashPtr, (ULONG)(READ_ARRAY<<16) 
  714.     | READ_ARRAY);
  715.      return(flWriteFault);
  716.      }
  717.   else
  718.      {
  719.      CFI_LONG_WRITE(flashPtr, (ULONG)(READ_ARRAY<<16) 
  720. | READ_ARRAY);
  721.      }
  722.        /* Now verify the write. */
  723.        if (tffscmpWords(&((long *)flashPtr)[wordsWritten/2],
  724.        &((long *)buffer)[wordsWritten/2], wordsThisWrite*2))
  725.    {
  726. #ifdef DEBUG_PRINT
  727.    DEBUG_PRINT("Debug: mtd: Buffer write verification failed (interleaved word mode)n");
  728. #endif
  729.    return flWriteFault;
  730.    }
  731.       else
  732.    {
  733. #ifdef DEBUG_PRINT
  734.   DEBUG_PRINT("Debug: mtd: Buffer write verification passed (interleaved word mode) at addr 0x%lxn", 
  735.   (ULONG) flashPtr);
  736. #endif
  737.    }
  738. }
  739.       wordsRemaining  -= wordsThisWrite;  /* That many fewer words 
  740.    * to go. */
  741.       wordsWritten    += wordsThisWrite;  /* That many more done. */
  742.       
  743.     }
  744. }
  745.     else   /* Part cannot handle writes to buffer, must write one byte at a time. */
  746. {
  747. }
  748.  
  749.   /* Put both devices back into read mode: */
  750.        CFI_LONG_WRITE(flashPtr, (ULONG) (READ_ARRAY<<16) | READ_ARRAY); 
  751.       return status;
  752.      }
  753. /***************************************************************************
  754.  * cfiscsDWordWrite - Write routine for devices on 32 bit bus.
  755.  *
  756.  * This code has not been tested since we have not had 32 bit devices we have
  757.  * had to support. It is provided for consistancy in the hope that it will
  758.  * reduce the effort needed by the folks who have to support such devices. To
  759.  * avoid endianness issues commands are written to all four bytes of the
  760.  * double word. 
  761.  *
  762.  * NOMANUAL
  763.  *
  764.  */
  765. LOCAL FLStatus cfiscsDWordWrite
  766.     (
  767.     FLFlash vol,
  768.     CardAddress address,
  769.     const void FAR1 *buffer,
  770.     int length,
  771.     int mode
  772.     )
  773.     {
  774.     FLStatus status = flOK;
  775.     FlashPTR flashPtr;
  776.     unsigned int from, eachWrite;
  777.     const char FAR1 *temp = (const char FAR1 *)buffer;
  778.     /* Set timeout to 5 seconds from now */
  779.     unsigned long writeTimeout = flMsecCounter + 5000;
  780.     /* Check if address and length are double word aligned */
  781.     if ((address & 0x3) || (length & 0x3))
  782. {
  783. #ifdef DEBUG_PRINT
  784. DEBUG_PRINT("Debug: Unaligned data - addr 0x%x - len 0x%xn",(UINT32) address, length);
  785. #endif
  786. return flBadParameter;
  787. }
  788.     if (flWriteProtected(vol.socket))
  789. return flWriteProtect;
  790. #ifdef SOCKET_12_VOLTS
  791.     if (thisCFI->vpp)
  792. checkStatus(flNeedVpp(vol.socket));
  793. #endif
  794.     if (thisCFI->maxBytesWrite > 1) /* multi-byte write supported */
  795. eachWrite = thisCFI->maxBytesWrite * vol.interleaving;
  796.     else
  797. eachWrite = 4; /* Max bus width */
  798.     for (from = 0; (int)from < length && status == flOK; from += eachWrite) 
  799.         {
  800. int thisLength = length - from;
  801. if (thisLength > (int)eachWrite)
  802.     thisLength = eachWrite;
  803. flashPtr = (FlashPTR) flMap(vol.socket, address + from);
  804.      do 
  805.          {
  806.     if ((thisCFI->maxBytesWrite > 1) && 
  807.     ((thisCFI->maxBytesWrite & 0x3) == 0))
  808. *(UINT32 *)flashPtr = (UINT32) ((WRITE_TO_BUFFER << 24) |
  809.       (WRITE_TO_BUFFER << 16) |
  810.       (WRITE_TO_BUFFER << 8)  |
  811.        WRITE_TO_BUFFER);
  812.     else
  813. *(UINT32 *)flashPtr = (UINT32) ((PROGRAM_WORD << 24) |
  814.       (PROGRAM_WORD << 16) |
  815.       (PROGRAM_WORD << 8)  |
  816.        PROGRAM_WORD);
  817.          } while (!(*flashPtr & SR_READY) && (flMsecCounter < writeTimeout));
  818. if (!(*flashPtr & SR_READY)) 
  819.          {
  820. #ifdef DEBUG_PRINT
  821.     DEBUG_PRINT("Debug: timeout error in CFISCS write.n");
  822. #endif
  823.     status = flWriteFault;
  824.     }
  825. /* If we are using the WRITE_TO_BUFFER command then we must program
  826.  * the buffer length
  827.  */
  828. if ((thisCFI->maxBytesWrite > 1) && 
  829.     ((thisCFI->maxBytesWrite & 0x3) == 0))
  830.     *flashPtr = (thisLength << 24 | thisLength << 16 
  831.  | thisLength << 8 | thisLength);
  832. tffscpyLongs(flashPtr,temp + from,thisLength);
  833. *(UINT32 *)flashPtr = (UINT32) ((CONFIRM_WRITE << 24) |
  834.       (CONFIRM_WRITE << 16) |
  835.       (CONFIRM_WRITE << 8)  |
  836.        CONFIRM_WRITE);
  837. *(UINT32 *)flashPtr = (UINT32) ((CONFIRM_WRITE << 24) |
  838.       (CONFIRM_WRITE << 16) |
  839.       (CONFIRM_WRITE << 8)  |
  840.        CONFIRM_WRITE);
  841. while (!(*(FlashDPTR) flashPtr & (SR_READY << 24)) && 
  842.         (flMsecCounter < writeTimeout))
  843.     ;
  844. if (!(flMsecCounter < writeTimeout)) 
  845.     {
  846. #ifdef DEBUG_PRINT
  847.     DEBUG_PRINT("Debug: timeout error in CFISCS write.n");
  848. #endif
  849.     status = flWriteFault;
  850.     }
  851. if (*flashPtr & WSM_ERROR) 
  852.     {
  853. #ifdef DEBUG_PRINT
  854.     DEBUG_PRINT("Debug: error in CFISCS write.n");
  855. #endif
  856.     status = (*flashPtr & SR_VPP_ERROR) ? flVppFailure : flWriteFault;
  857.     *(UINT32 *)flashPtr = (UINT32) ((CLEAR_STATUS << 24) |
  858.   (CLEAR_STATUS << 16) |
  859.   (CLEAR_STATUS << 8)  |
  860.    CLEAR_STATUS);
  861.     }
  862. *(UINT32 *)flashPtr = (UINT32) ((READ_ARRAY << 24) |
  863.             (READ_ARRAY << 16) |
  864.       (READ_ARRAY << 8)  |
  865.        READ_ARRAY);
  866. }
  867. #ifdef SOCKET_12_VOLTS
  868.     if (thisCFI->vpp)
  869. flDontNeedVpp(vol.socket);
  870. #endif
  871.     flashPtr = (FlashPTR) flMap(vol.socket, address);
  872.     /* verify the data */
  873.     if (status == flOK && tffscmpWords((void FAR0 *) flashPtr, (void FAR1 *) buffer,length)) 
  874. {
  875. #ifdef DEBUG_PRINT
  876.     DEBUG_PRINT("Debug: CFISCS write failed in verification.n");
  877. #endif
  878. status = flWriteFault;
  879. }
  880.     return status;
  881.     }
  882. #ifdef INTERLEAVED_MODE_REQUIRES_32BIT_WRITES
  883. /***************************************************************************
  884.  * cfiscsInterleavedWordErase - Erase specified number of blocks
  885.  *
  886.  * Given the first block and number of contiguous blocks to erase, this 
  887.  * routine will erase the content of the specified region. The routine does
  888.  * not support featurees like "Suspend Erase" or "Queued Erase" so the device
  889.  * stays busy until all specified blocks have been erased. These features need
  890.  * to be supported by the TrueFFS core to be applicable here.
  891.  *
  892.  * NOMANUAL
  893.  *
  894.  */
  895. LOCAL FLStatus cfiscsInterleavedWordErase
  896.     (
  897.     FLFlash vol,
  898.     int firstEraseBlock,
  899.     int numberOfEraseBlocks
  900.     )
  901.     {
  902.     FLStatus status = flOK;       /* unless proven otherwise */
  903.     int iBlock;
  904.     if (flWriteProtected(vol.socket))
  905.         return flWriteProtect;
  906. #ifdef SOCKET_12_VOLTS
  907.     if (thisCFI->vpp)
  908.         checkStatus(flNeedVpp(vol.socket));
  909. #endif
  910.     
  911.     for (iBlock = firstEraseBlock; 
  912.  iBlock < firstEraseBlock + numberOfEraseBlocks && status == flOK;
  913.  iBlock++) 
  914.         {
  915.         FLBoolean finished;
  916. FlashWPTR flashPtr = (FlashWPTR) flMap(vol.socket,
  917. iBlock * vol.erasableBlockSize);
  918. CFI_LONG_WRITE(flashPtr, (ULONG) (SETUP_BLOCK_ERASE <<16)|SETUP_BLOCK_ERASE);
  919. CFI_LONG_WRITE(flashPtr, (ULONG) (CONFIRM_ERASE <<16)|CONFIRM_ERASE);
  920. /*   while (flashPtr[ix * thisCFI->interleaveFactor] != 0x80); */
  921. do 
  922.     {
  923.     finished = FALSE;
  924.     if ((flashPtr[0] == SR_READY) &&
  925.     (flashPtr[1] == SR_READY))
  926. {
  927. finished = TRUE;
  928. if (CFI_WORD_READ(flashPtr) & WSM_ERROR) 
  929.     {
  930. #ifdef DEBUG_PRINT
  931.   DEBUG_PRINT("Debug: CFISCS erase error on device onen");
  932. #endif
  933.     status = (CFI_WORD_READ(flashPtr) & SR_VPP_ERROR) 
  934.     ?  flVppFailure : flWriteFault;
  935.     CFI_LONG_WRITE(flashPtr, (ULONG) CLEAR_STATUS);
  936.     }
  937. else if (CFI_WORD_READ(&flashPtr[1]) & WSM_ERROR) 
  938.     {
  939. #ifdef DEBUG_PRINT
  940.   DEBUG_PRINT("Debug: CFISCS erase error on device twon");
  941. #endif
  942.     status = ((CFI_WORD_READ(&flashPtr[1])) & (SR_VPP_ERROR)) 
  943.     ?  flVppFailure : flWriteFault;
  944.     CFI_LONG_WRITE(flashPtr, (ULONG) (CLEAR_STATUS <<16) & 0xffff0000);
  945.     }
  946. CFI_LONG_WRITE(flashPtr, (ULONG) (READ_ARRAY <<16)|READ_ARRAY);
  947. }
  948.     } while (!finished);
  949.         }
  950. #ifdef SOCKET_12_VOLTS
  951.     if (thisCFI->vpp)
  952.         flDontNeedVpp(vol.socket);
  953. #endif
  954.     return status;
  955.     }
  956. #else /* !INTERLEAVED_MODE_REQUIRES_32BIT_WRITES */
  957. /***************************************************************************
  958.  * cfiscsErase - Erase specified number of blocks
  959.  *
  960.  * Given the first block and number of contiguous blocks to erase, this 
  961.  * routine will erase the content of the specified region. The routine does
  962.  * not support featurees like "Suspend Erase" or "Queued Erase" so the device
  963.  * stays busy until all specified blocks have been erased. These features need
  964.  * to be supported by the TrueFFS core to be applicable here.
  965.  *
  966.  * Each interleaved device is erased independently. The core does not
  967.  * compensate for interleaving and expects interleaving to be handled here.
  968.  *
  969.  * NOMANUAL
  970.  *
  971.  */
  972. LOCAL FLStatus cfiscsErase
  973.     (
  974.     FLFlash vol,
  975.     int firstEraseBlock,
  976.     int numberOfEraseBlocks
  977.     )
  978.     {
  979.     FLStatus status = flOK;       /* unless proven otherwise */
  980.     int iBlock;
  981.     if (flWriteProtected(vol.socket))
  982.         return flWriteProtect;
  983. #ifdef SOCKET_12_VOLTS
  984.     if (thisCFI->vpp)
  985.         checkStatus(flNeedVpp(vol.socket));
  986. #endif
  987.     
  988.     for (iBlock = firstEraseBlock; 
  989.  iBlock < firstEraseBlock + numberOfEraseBlocks && status == flOK;
  990.  iBlock++) 
  991.         {
  992. int ix;
  993.         FLBoolean finished;
  994. FlashPTR flashPtr = (FlashPTR) flMap(vol.socket,
  995. iBlock * vol.erasableBlockSize);
  996. for(ix=0; ix < vol.interleaving; ix++)
  997.     {
  998.     flashPtr[ix * thisCFI->interleaveFactor] = SETUP_BLOCK_ERASE;
  999.     flashPtr[ix * thisCFI->interleaveFactor] = CONFIRM_ERASE;
  1000.     flashPtr[ix * thisCFI->interleaveFactor] = CONFIRM_ERASE;
  1001.     while (flashPtr[ix * thisCFI->interleaveFactor] != 0x80);
  1002.     do 
  1003. {
  1004. finished = TRUE;
  1005. if (!(flashPtr[ix * thisCFI->interleaveFactor] & SR_READY))
  1006. finished = FALSE;
  1007. else 
  1008.     {
  1009.     if (flashPtr[ix * thisCFI->interleaveFactor] & WSM_ERROR) 
  1010. {
  1011. #ifdef DEBUG_PRINT
  1012.   DEBUG_PRINT("Debug: CFISCS erase error on device %d.n", ix);
  1013. #endif
  1014. status = (flashPtr[ix * thisCFI->interleaveFactor] 
  1015.  & SR_VPP_ERROR) ?  flVppFailure : flWriteFault;
  1016. flashPtr[ix * thisCFI->interleaveFactor] = CLEAR_STATUS;
  1017. }
  1018.     flashPtr[ix * thisCFI->interleaveFactor] = READ_ARRAY;
  1019.     }
  1020. } while (!finished);
  1021.     }
  1022. }
  1023. #ifdef SOCKET_12_VOLTS
  1024.     if (thisCFI->vpp)
  1025.         flDontNeedVpp(vol.socket);
  1026. #endif
  1027.     return status;
  1028.     }
  1029. #endif /* INTERLEAVED_MODE_REQUIRES_32BIT_WRITES */
  1030. /***************************************************************************
  1031.  * cfiscsIdentify - Identification routine for devices conforming to CFI/SC
  1032.  *
  1033.  * Identifies media based on SCS/CFI and registers as an MTD for such.
  1034.  * This routine will be placed on the MTD list in custom.h. It must be an 
  1035.  * extern routine. On successful identification, the Flash structure is filled 
  1036.  * out and the write and erase routines registered. 
  1037.  *
  1038.  * Parameters:
  1039.  *      vol             : Pointer identifying drive 
  1040.  *
  1041.  * Returns:
  1042.  *      FLStatus        : 0 on positive identificaion, failed otherwise 
  1043.  *
  1044.  * URL:http://developer.intel.com/design/flcomp/applnots/29220404.pdf 
  1045.  *
  1046.  * NOMANUAL
  1047.  *
  1048.  */
  1049. FLStatus cfiscsIdentify
  1050.     (
  1051.     FLFlash vol
  1052.     )
  1053.     {
  1054.     FlashPTR flashPtr = (FlashPTR) flMap(vol.socket, 0);
  1055.     FlashWPTR flashWPtr = (FlashWPTR) flashPtr;
  1056.     FlashDPTR flashDPtr = (FlashDPTR) flashPtr;
  1057.     unsigned primaryTable, secondaryTable;
  1058.     char priIdStr[ID_STR_LENGTH + 1] = PRIMARY_ID_STR;
  1059. #ifdef DEBUG_PRINT
  1060.     DEBUG_PRINT("Debug: entering CFISCS identification routine.n");
  1061. #endif
  1062.     flSetWindowBusWidth(vol.socket, 16);/* use 16-bits */
  1063.     flSetWindowSpeed(vol.socket, 120);  /* 120 nsec. */
  1064.     flSetWindowSize(vol.socket, 2);       /* 8 KBytes */
  1065.     vol.mtdVars = &mtdVars[flSocketNoOf(vol.socket)];
  1066.     /* Is this an 8 bit device */
  1067.     flashPtr[0x55] = READ_ARRAY;
  1068.     flashPtr[0x55] = QUERY;
  1069.     
  1070.     if (flashPtr[0x10] == 0x51 && /* 'Q' */
  1071.         flashPtr[0x11] == 0x52 && /* 'R' */
  1072.         flashPtr[0x12] == 0x59)   /* 'Y' */
  1073.         {
  1074. #ifdef DEBUG_PRINT
  1075.         DEBUG_PRINT ("Debug: detected single 8 bit devicen");
  1076. #endif
  1077.         thisCFI->multiplier = 1;
  1078. thisCFI->interleaveFactor = 1;
  1079.         vol.interleaving = 1;
  1080. vol.type = (FlashType) ((flashPtr[0] << 8) | flashWPtr[1]);
  1081. vol.write = cfiscsByteWrite;
  1082.         goto getCFI;
  1083.         }
  1084.     /* Reset to READ_ARRAY and retry. Maybe 16 bit addressing 
  1085.      */
  1086.     flashPtr[0x55] = READ_ARRAY;
  1087.     flashWPtr[0x55] = (USHORT) ((QUERY << 8) | QUERY); 
  1088.     /* Check for two interleaved 8 bit parts */
  1089.     if (flashPtr[0x20] == 0x51 && /* 'Q' */
  1090.         flashPtr[0x21] == 0x51 && /* 'Q' */
  1091.         flashPtr[0x22] == 0x52 && /* 'R' */
  1092.         flashPtr[0x23] == 0x52 && /* 'R' */
  1093.         flashPtr[0x24] == 0x59 && /* 'Y' */
  1094.         flashPtr[0x25] == 0x59)   /* 'Y' */
  1095.      {
  1096. /* Let's try turning one off */
  1097. CFI_WORD_WRITE((FlashWPTR)(&flashPtr[0x55]), READ_ARRAY);
  1098. if (flashPtr[0x20] != 0x51) /* Turned off successfully */
  1099.     {
  1100.     thisCFI->multiplier = 2;
  1101.     thisCFI->interleaveFactor = 1;
  1102.     vol.interleaving =2;
  1103.     vol.type = (FlashType) ((flashWPtr[0] << 8) | flashWPtr[1]);
  1104.     vol.write = cfiscsByteWrite;
  1105. #ifdef DEBUG_PRINT
  1106.     DEBUG_PRINT ("Debug: detected two 8 bit devicesn");
  1107. #endif
  1108.     goto getCFI;
  1109.     }
  1110. }
  1111.     /* a 16 bit device in 16 bit mode */
  1112.     if (flashPtr[0x20] == 0x51 && /* 'Q' */
  1113.         flashPtr[0x21] == 0x00 && /* NUL */
  1114.         flashPtr[0x22] == 0x52 && /* 'R' */
  1115.         flashPtr[0x23] == 0x00 && /* NUL */
  1116.         flashPtr[0x24] == 0x59 && /* 'Y' */
  1117.         flashPtr[0x25] == 0x00)   /* NUL */
  1118.         {
  1119.         thisCFI->multiplier = 2;
  1120. thisCFI->interleaveFactor = 1;
  1121. vol.interleaving = 1;
  1122. vol.type = (FlashType) ((flashWPtr[0] << 8) | (flashWPtr[1]));
  1123. vol.write = cfiscsWordWrite;
  1124. #ifdef DEBUG_PRINT
  1125.         DEBUG_PRINT ("Debug: detected one 16 bit devicen");
  1126. #endif
  1127. goto getCFI;
  1128. }
  1129.     /* If we have a 16 bit device in 8 bit mode it should ID correctly */
  1130.     if (flashPtr[0x20] == 0x51 && /* 'Q' */
  1131.         flashPtr[0x21] == 0x51 && /* 'Q' */
  1132.         flashPtr[0x22] == 0x52 && /* 'R' */
  1133.         flashPtr[0x23] == 0x52 && /* 'R' */
  1134.         flashPtr[0x24] == 0x59 && /* 'Y' */
  1135.         flashPtr[0x25] == 0x59)   /* 'Y' */
  1136.         {
  1137. thisCFI->multiplier = 2;
  1138. #ifdef DEBUG_PRINT
  1139.         DEBUG_PRINT ("Debug: detected a 16 bit device in 8 bit moden");
  1140. #endif
  1141.      vol.interleaving =1;
  1142. thisCFI->interleaveFactor = 1;
  1143. vol.type = (FlashType) ((flashWPtr[0] << 8) | flashWPtr[1]);
  1144. vol.write = cfiscsByteWrite;
  1145. goto getCFI;
  1146.      }
  1147.     /* Reset to READ_ARRAY and retry. Maybe 32 bit addressing 
  1148.      */
  1149.     flashWPtr[0x55] = (USHORT) ((READ_ARRAY << 8) | READ_ARRAY); 
  1150.     flashDPtr[0x55] = (ULONG) (QUERY << 24| QUERY <<16 | QUERY << 8 | QUERY); 
  1151.     /* A 32 bit device in 8 bit mode and two 16 bit deivec in 8 bit mode will
  1152.      * appear the same to the querry process. The only way to make the
  1153.      * distinction is to try and set one device back to read array mode while
  1154.      * the other remains in query mode */
  1155.     if (flashPtr[0x40] == 0x51 && /* 'Q' */
  1156.         flashPtr[0x41] == 0x51 && /* 'Q' */
  1157.         flashPtr[0x42] == 0x51 && /* 'Q' */
  1158.         flashPtr[0x43] == 0x51 && /* 'Q' */
  1159.         flashPtr[0x44] == 0x52 && /* 'R' */
  1160.         flashPtr[0x45] == 0x52 && /* 'R' */
  1161.         flashPtr[0x46] == 0x52 && /* 'R' */
  1162.         flashPtr[0x47] == 0x52 && /* 'R' */
  1163.         flashPtr[0x48] == 0x59 && /* 'Y' */
  1164.         flashPtr[0x49] == 0x59 && /* 'Y' */
  1165.         flashPtr[0x4a] == 0x59 && /* 'Y' */
  1166.         flashPtr[0x4b] == 0x59)   /* 'Y' */
  1167.         {
  1168. /* See if we can turn one off */
  1169. flashPtr[0x154] = READ_ARRAY;
  1170. if ((flashPtr[0x40] != 0x51) && (flashPtr[0x41] == 0x51))
  1171.     { /* Turned one device off successfully */
  1172.     flashPtr[0x154] = QUERY;  /* turn it back on to querry mode */
  1173.     vol.interleaving = 2;
  1174.     vol.type = (FlashType) ((flashWPtr[0] << 8) | (flashWPtr[4]));
  1175. #ifdef DEBUG_PRINT
  1176.     DEBUG_PRINT ("Debug: detected two 16 bit device, 8 bit interleaved(2)n");
  1177. #endif
  1178.     }
  1179. else
  1180.     {
  1181.     vol.interleaving =1;
  1182. #ifdef DEBUG_PRINT
  1183.     DEBUG_PRINT ("Debug: detected a 32 bit device in 8 bit moden");
  1184. #endif
  1185.     vol.type = (FlashType) ((flashDPtr[0] << 8) | flashDPtr[1]);
  1186.     }
  1187.         thisCFI->multiplier = 4;
  1188. thisCFI->interleaveFactor = 1;
  1189. vol.write = cfiscsByteWrite;
  1190. goto getCFI;
  1191. }
  1192.     /* Is it a single 32 bit device */
  1193.     if (flashPtr[0x40] == 0x51 && /* 'Q' */
  1194.         flashPtr[0x41] == 0x00 && /* NUL */
  1195.         flashPtr[0x42] == 0x00 && /* NUL */
  1196.         flashPtr[0x43] == 0x00 && /* NUL */
  1197.         flashPtr[0x44] == 0x52 && /* 'R' */
  1198.         flashPtr[0x45] == 0x00 && /* NUL */
  1199.         flashPtr[0x46] == 0x00 && /* NUL */
  1200.         flashPtr[0x47] == 0x00 && /* NUL */
  1201.         flashPtr[0x48] == 0x59 && /* 'Y' */
  1202.         flashPtr[0x49] == 0x00 && /* NUL */
  1203.         flashPtr[0x4a] == 0x00 && /* NUL */
  1204.         flashPtr[0x4b] == 0x00)   /* NUL */
  1205.         {
  1206. #ifdef DEBUG_PRINT
  1207.         DEBUG_PRINT ("Debug: detected a 32 bit device in 32 bit moden");
  1208. #endif
  1209. thisCFI->multiplier = 4;
  1210. thisCFI->interleaveFactor = 1;
  1211. vol.interleaving = 1;
  1212. vol.type = (FlashType) ((flashDPtr[0] << 8) | flashDPtr[1]);
  1213. vol.write = cfiscsDWordWrite;
  1214. goto getCFI;
  1215. }
  1216.     /* Two 16 bit devices in 16 bit mode */
  1217.     if (flashPtr[0x40] == 0x51 && /* 'Q' */
  1218.         flashPtr[0x41] == 0x00 && /* NUL */
  1219.         flashPtr[0x42] == 0x51 && /* 'Q' */
  1220.         flashPtr[0x43] == 0x00 && /* NUL */
  1221.         flashPtr[0x44] == 0x52 && /* 'R' */
  1222.         flashPtr[0x45] == 0x00 && /* NUL */
  1223.         flashPtr[0x46] == 0x52 && /* 'R' */
  1224.         flashPtr[0x47] == 0x00 && /* NUL */
  1225.         flashPtr[0x48] == 0x59 && /* 'Y' */
  1226.         flashPtr[0x49] == 0x00 && /* NUL */
  1227.         flashPtr[0x4a] == 0x59 && /* 'Y' */
  1228.         flashPtr[0x4b] == 0x00)   /* NUL */
  1229.         {
  1230. #ifdef DEBUG_PRINT
  1231.         DEBUG_PRINT ("Debug: Detected two 16 bit devices in 16 bit mode(3)n");
  1232. #endif
  1233. thisCFI->multiplier = 4;
  1234. thisCFI->interleaveFactor = 2;
  1235. vol.interleaving = 2;
  1236. vol.type = (FlashType) (flashPtr[0] << 8 | 
  1237. flashPtr[thisCFI->multiplier]);
  1238. vol.write = cfiscsInterleavedWordWrite;
  1239. goto getCFI;
  1240. }
  1241.     /* If we get here the device is probably not CFI */
  1242. #ifdef DEBUG_PRINT
  1243.     DEBUG_PRINT ("Debug: Failed to identify CFI... n Exiting n");
  1244. #endif
  1245.     flashDPtr[0x55] = (ULONG) (READ_ARRAY << 24| READ_ARRAY <<16 
  1246.      | READ_ARRAY << 8 | READ_ARRAY); 
  1247.     return flUnknownMedia;
  1248. getCFI:
  1249.     /* check the command set ID */
  1250.     thisCFI->commandSetId = flashPtr[0x13 * thisCFI->multiplier] | 
  1251. ((unsigned)flashPtr[0x14 * thisCFI->multiplier] << 8);
  1252.     if (thisCFI->commandSetId != INTEL_COMMAND_SET &&
  1253.       thisCFI->commandSetId != AMDFUJ_COMMAND_SET) 
  1254.         {
  1255. #ifdef DEBUG_PRINT
  1256.     DEBUG_PRINT("Debug: did not recognize command set.n");
  1257. #endif
  1258.         return flUnknownMedia;
  1259.         }
  1260.     /* get address for primary algorithm extended table. */
  1261.     primaryTable = flashPtr[0x15 * thisCFI->multiplier] |
  1262.  ((unsigned)flashPtr[0x16 * thisCFI->multiplier] << 8);
  1263.     /* check alternate command set ID. */
  1264.     thisCFI->altCommandSetId = flashPtr[0x17 * thisCFI->multiplier] | 
  1265. ((unsigned)flashPtr[0x18 * thisCFI->multiplier] << 8);
  1266.     if (thisCFI->altCommandSetId != INTEL_ALT_COMMAND_SET &&
  1267.         thisCFI->altCommandSetId != AMDFUJ_ALT_COMMAND_SET &&
  1268.         thisCFI->altCommandSetId != ALT_NOT_SUPPORTED)
  1269.         return flUnknownMedia;
  1270.     /* get address for secondary algorithm extended table. */
  1271.     secondaryTable = flashPtr[0x19 * thisCFI->multiplier] |
  1272.    ((unsigned)flashPtr[0x1a * thisCFI->multiplier] << 8);
  1273.     thisCFI->vpp = flashPtr[0x1d * thisCFI->multiplier];
  1274.     vol.erasableBlockSize = (flashPtr[0x2f * thisCFI->multiplier] |
  1275.  ((unsigned)flashPtr[0x30 * thisCFI->multiplier]) << 8) *
  1276.   0x100L;
  1277.     /* we reserve one erase block for NVRAM usage */
  1278. #ifdef SAVE_NVRAM_REGION
  1279.     vol.chipSize = (1L << flashPtr[0x27 * thisCFI->multiplier]) - 
  1280. vol.erasableBlockSize;
  1281. #else
  1282.     vol.chipSize = (1L << flashPtr[0x27 * thisCFI->multiplier]);
  1283. #endif
  1284.     vol.erasableBlockSize *= vol.interleaving;
  1285. #ifdef BUFFERED_WRITE_BROKEN
  1286.     thisCFI->maxBytesWrite = 1;
  1287. #else
  1288.     thisCFI->maxBytesWrite = 1L << (flashPtr[0x2a * thisCFI->multiplier] |
  1289.    ((unsigned)flashPtr[0x2b * thisCFI->multiplier] << 8));
  1290. #endif /* BUFFERED_WRITE_BROKEN */
  1291.     /* In this part we access the primary extended table implemented by Intel.
  1292.      * If the device uses a different extended table, it should be accessed
  1293.      * according to the vendor specifications. 
  1294.      */
  1295.     if ((primaryTable) && (thisCFI->commandSetId == INTEL_COMMAND_SET)) 
  1296.         {
  1297.         /* look for the primary table identification string "PRI" */
  1298.         if (priIdStr[0] != flashPtr[primaryTable * thisCFI->multiplier] ||
  1299.     priIdStr[1] != flashPtr[(primaryTable + 1) * thisCFI->multiplier] ||
  1300.     priIdStr[2] != flashPtr[(primaryTable + 2) * thisCFI->multiplier])
  1301.     {
  1302. #ifdef DEBUG_PRINT
  1303.     DEBUG_PRINT ("Debug: No primary ID @ offset 0x%xn", primaryTable);
  1304. #endif
  1305.             return flUnknownMedia;
  1306.     }
  1307.     thisCFI->optionalCommands = flashPtr[(primaryTable + 5) * thisCFI->multiplier] |
  1308. ((long)flashPtr[(primaryTable + 6) *
  1309.   thisCFI->multiplier] << 8) |
  1310. ((long)flashPtr[(primaryTable + 7) *
  1311.   thisCFI->multiplier] << 16) |
  1312. ((long)flashPtr[(primaryTable + 8) *
  1313.   thisCFI->multiplier] << 24);
  1314.     thisCFI->afterSuspend = flashPtr[(primaryTable + 9) * thisCFI->multiplier];
  1315. }
  1316.     else 
  1317.         {
  1318. thisCFI->optionalCommands = 0;
  1319. thisCFI->afterSuspend = 0;
  1320. }
  1321.     /* Make sure this comes at the end since the device is set to READ_ARRAY
  1322.      * mode prior to the return
  1323.      */
  1324.     if (cfiscsGetChipCount(&vol) != flOK)
  1325. return flUnknownMedia;
  1326. #ifdef DEBUG_PRINT
  1327.     DEBUG_PRINT ("Debug: No of chips detected is %dn", vol.noOfChips);
  1328. #endif
  1329. #ifdef INTERLEAVED_MODE_REQUIRES_32BIT_WRITES
  1330.     vol.erase = cfiscsInterleavedWordErase;
  1331. #else  /* !INTERLEAVED_MODE_REQUIRES_32BIT_WRITES */
  1332.     vol.erase = cfiscsErase;
  1333. #endif /* INTERLEAVED_MODE_REQUIRES_32BIT_WRITES */
  1334.     /* Might have to do this on a bus width basis but for now it seems to
  1335.      * work with Intel devices.
  1336.      */
  1337.     flashPtr[0] = READ_ARRAY;
  1338.     flashPtr[1] = READ_ARRAY;
  1339.     flashPtr[2] = READ_ARRAY;
  1340.     flashPtr[3] = READ_ARRAY;
  1341.     return flOK;
  1342.     }