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

VxWorks

开发平台:

C/C++

  1. /* cfiamd.c - MTD for AMD parts that comply with CFI */
  2.  
  3. /* Copyright 1984-2002 Wind River Systems, Inc. */
  4. #include "copyright_wrs.h"
  5. /* FAT-FTL Lite Software Development Kit
  6.  * Copyright (C) M-Systems Ltd. 1995-2001       */
  7. /*
  8. modification history
  9. --------------------
  10. 01l,24jun02,nrv  fixing the condition where flashPtr[0x24] is checked twice
  11. 01k,30apr02,nrv  cleaned up the code by removing local var gif
  12. 01j,09apr02,yp   fixed SPR 75069. reworked write routines so status chek would work.
  13. 01i,28mar02,nrv  vol.mtdVars is dereferenced before the pointer is set in
  14.                  cfiAmdIdentify
  15. 01h,12feb02,yp   Written based on cfiscs.c
  16. */
  17. /*
  18. DESCRIPTION
  19. This library provides an MTD for devices that conform to the Common Flash 
  20. Interface (CFI) and the AMD/Fujitsu command set. The library provides 
  21. identification, erase and write routines for 8 and 16 bit devices in 
  22. native or byte mode. Support is also added for word width devices 
  23. interleaved word wide where bytes 0 and 1 would be on device one 
  24. and bytes 2 and 3 would be on device two, and so on. Support is also present 
  25. for configurations that only permit double word width writes.
  26. The identification process supports byte, word, and double word width devices 
  27. as specified by the CFI query process. Vendr specific extentions are made 
  28. available from an instance specific data structure, referred to in this file 
  29. as thisCFI. 
  30. In addition to supporting a boot code region through the format process this
  31. driver is also able to reserve the last erase block of each device in the array
  32. so the vxWorks may use this region as NVRAM if the macro SAVE_NVRAM_REGION is 
  33. defined.
  34. The low voltage devices that support boot blocks get no special treatment in 
  35. this driver. The asymmetric regions are regocgnized from the erase block region
  36. information retreaved during CFI identification. They can, therefore be used by 
  37. the the file system just like any other sector, if they are not used for boot 
  38. purposes. Since TrueFFS does not support uneven sector distribution, the size of 
  39. the largest sector is taken as the erase block size. When an erase request 
  40. corresponds to the boot block region, all sectors in the boot block are erased.
  41. As such, the NVRAM area saved on a top boot device is the entire boot block and 
  42. not just the last sector as one might expect.
  43. Based on the observation that CFI data on the sector distribution on AMD devices
  44. always describes bottom boot devices, this driver does an "autoselect" to 
  45. determine the boot block type for proper interpretation of the device geometry 
  46. data. The erase process assumes that bottom boot devices have the boot block 
  47. located in sector zero. The first erase block encountered in an erase request 
  48. that has a sector size other than vol.erasableBlockSize on top boot devices is 
  49. assumed to be the boot block anchor on top boot devices.
  50. NOMANUAL
  51. */
  52. #include <stdio.h>
  53. #include "tffs/flflash.h"
  54. #include "tffs/backgrnd.h"
  55. #define  MAXSECTORS 128 /* should work with any value */
  56. typedef enum
  57.     {
  58.     BOOTBLOCK_NONE,
  59.     BOOTBLOCK_TOP,
  60.     BOOTBLOCK_BOTTOM
  61.     }BOOTBLOCK;
  62. typedef union
  63.     {
  64.     UCHAR uchar[4];
  65.     UINT32 uint32;
  66.     } CFI_DWORD;
  67. typedef union
  68.     {
  69.     UCHAR uchar[2];
  70.     USHORT ushort;
  71.     } CFI_WORD;
  72.     
  73. /* Instance specific CFI data so that a system may have more than one CFI
  74.  * device. */
  75. typedef struct {
  76.   unsigned         commandSetId;            /* id of a specific command set. */
  77.   unsigned         altCommandSetId;         /* id of alternate command set.  */
  78.   FLBoolean        wordMode;                /* TRUE - word mode.             */
  79.     /* FALSE - byte mode.            */
  80.   int              multiplier;              /* the number of bytes between   */
  81.     /* 1st Q and 1st R in query      */
  82.   int    interleaveWidth;     /* 1 - byte 2 - word interleaved */
  83.   unsigned         maxBytesWrite;           /* maximum number of bytes       */
  84.     /* in multi-byte write.          */
  85.   FLBoolean        vpp;                     /* if = TRUE, need vpp.          */
  86.   long             optionalCommands;        /* optional commands supported   */
  87.     /* (1 = yes, 0 = no):            */
  88.     /* bit 0 - chip erase.           */
  89.     /* bit 1 - suspend erase.        */
  90.     /* bit 2 - suspend write         */
  91.     /* bit 3 - lock/unlock.          */
  92.     /* bit 4 - queued erase.         */
  93.   unsigned         afterSuspend;            /* functions supported after     */
  94.     /* suspend (1 = yes, 0 = no):    */
  95.     /* bit 0 - write after erase     */
  96.     /*         suspend.              */
  97.   int     sectorDefs;     /* Number of sector definitions  */
  98.   struct {     /* sector descriptions as found  */
  99.       long     secSize;     /* in CFI query.       */
  100.       int     numSecs;     /*      */
  101.   }secDesc[8];     /* assume 8 is enough      */
  102.   struct {     /*      */
  103.       long    sectorSize;     /* sector size       */
  104.       UINT32    sectorBaseAdrs;     /* base address of sector      */
  105.   } secInfo[MAXSECTORS];     /* per sector info      */
  106.   UINT32 unlockAddr1;     /* offset for first unlock      */
  107.   UINT32 unlockAddr2;     /* offset for 2nd unlock      */
  108.   int sectorsInCFI;     /* sector count for device      */
  109.   int bootBlockSectors;     /* sectors that makeup boot block*/
  110.   BOOTBLOCK bootBlockType;     /* Top, Bottom or None      */
  111.       
  112. } CFI;
  113. LOCAL CFI mtdVars[DRIVES];
  114. /* defines */
  115. /* Save the last erase block on each device discovered in the array 
  116.  * for NVRAM */
  117. #define SAVE_NVRAM_REGION
  118. /* disable debugging */
  119. #undef CFI_DEBUG
  120. #ifdef CFI_DEBUG
  121. #define DEBUG_PRINT    printf
  122. #else
  123. #undef DEBUG_PRINT
  124. #endif
  125. #ifndef _BYTE_ORDER
  126. #error "Error: _BYTE_ORDER needs to be #define'd.  Try #include "vxWorks.h" "
  127. #endif
  128. #if (_BYTE_ORDER == _BIG_ENDIAN)
  129. #define CFI_LONGSWAP(x) LONGSWAP(x) /* swap everything in a long word */
  130. #define CFI_WORDSWAP(x) WORDSWAP(x) /* swap the shorts in a long */
  131. #define CFI_BYTESWAP(x) ( ( (x & 0xff) << 8) | ( (x >> 8) & 0xff) )  /* Swap bytes in a short */
  132. #else
  133. #define CFI_LONGSWAP(x) (x) /* pass it as is */
  134. #define CFI_WORDSWAP(x) (x) /* pass it as is */
  135. #define CFI_BYTESWAP(x) (x) /* pass it as is */
  136. #endif /* _BYTE_ORDER == _BIG_ENDIAN */
  137. #define CFI_LONG_WRITE(addr, data)  (*(ULONG *)addr = (ULONG)(CFI_WORDSWAP(data)))
  138. #define CFI_WORD_WRITE(addr, data)  (*(USHORT *)addr = (USHORT)(CFI_BYTESWAP(data)))
  139. #define CFI_WORD_READ(addr)         (CFI_BYTESWAP(*(USHORT *)addr))
  140. #define CFI_LONG_READ(addr)         (CFI_WORDSWAP(*(ULONG *)addr))
  141. /* command set IDs */
  142. #define INTEL_COMMAND_SET      0x0001
  143. #define AMDFUJ_COMMAND_SET     0x0002
  144. #define INTEL_ALT_COMMAND_SET  0x0001
  145. #define AMDFUJ_ALT_COMMAND_SET 0x0004
  146. #define ALT_NOT_SUPPORTED      0x0000
  147. /* CFI identification strings */
  148. #define ID_STR_LENGTH      3
  149. #define QUERY_ID_STR       "QRY"
  150. #define PRIMARY_ID_STR     "PRI"
  151. #define ALTERNATE_ID_STR   "ALT"
  152. /* commands */
  153. #define AMD_SETUP_ERASE 0x80
  154. #define AMD_SETUP_WRITE 0xa0
  155. #define AMD_READ_ID  0x90
  156. #define AMD_SUSPEND_ERASE 0xb0
  157. #define AMD_SECTOR_ERASE 0x30
  158. #define AMD_RESUME_ERASE 0x30
  159. #define AMD_READ_ARRAY 0xf0
  160. #define AMD_NO_UNLOCK_ADDR 0xffffffffL
  161. #define AMD_UNLOCK_1 0xaa
  162. #define AMD_UNLOCK_2 0x55
  163. #define AMD_WW_UNLOCK_ADDR1 0x555u /* Word wide devices */
  164. #define AMD_WW_UNLOCK_ADDR2 0x2aau  /* Word wide devices */
  165. #define AMD_BW_UNLOCK_ADDR1 0xaaau  /* Byte wide devices */
  166. #define AMD_BW_UNLOCK_ADDR2 0x555u  /* Byte wide devices */
  167. #define AMD_D2 4 /* Toggles when erase suspended */
  168. #define AMD_D5 0x20 /* Set when programming timeout */
  169. #define AMD_D6 0x40 /* Toggles when programming */
  170. /* optional commands support */
  171. #define CHIP_ERASE_SUPPORT           0x0001
  172. #define SUSPEND_ERASE_SUPPORT        0x0002
  173. #define SUSPEND_WRITE_SUPPORT        0x0004
  174. #define LOCK_SUPPORT                 0x0008
  175. #define QUEUED_ERASE_SUPPORT         0x0010
  176. #define QUERY 0x98
  177. /* supported functions after suspend */
  178. #define WRITE_AFTER_SUSPEND_SUPPORT  0x0001
  179. #define thisCFI   ((CFI *)vol.mtdVars)
  180. /* JEDEC IDs */
  181. /* 1.8 volt devices */
  182. #if 0
  183. /* Leaving out this one since it will complicate driver  */
  184. #define Am39BDS643G_FLASH 0x017e /* top boot only 95 64KB, 4 16KB,
  185.   31 64KB, and 4 16KB sectors*/
  186. #endif
  187.  
  188. #define Am29DS163DT_FLASH 0x0195 /* 8 8KB, and 31 64KB sectors */
  189. #define Am29DS163DB_FLASH 0x0196 /* 8 8KB, and 31 64KB sectors */
  190. #define Am29DS323DT_FLASH 0x01b7 /* 8 8KB, and 63 64KB sectors */
  191. #define Am29DS323DB_FLASH 0x01b8 /* 8 8KB, and 63 64KB sectors */
  192. #define Am29PDS322DT_FLASH 0x0101 /* 8 8KB, and 63 64KB sectors */
  193. #define Am29PDS322DB_FLASH 0x0100 /* 8 8KB, and 63 64KB sectors */
  194. #define Am29SL160CT_FLASH 0x01e4 /* 8 8KB, and 31 64KB sectors */
  195. #define Am29SL160CB_FLASH 0x01e7 /* 8 8KB, and 31 64KB sectors */
  196. /* 3.0 volt devices */
  197. #define Am29LV160BT_FLASH 0x01c4 /* 31 64KB, 1 32KB, 2 8KB, and 1 16KB sectors */
  198. #define Am29LV160BB_FLASH       0x0149 /* 1 16KB, 2 8KB, 1 32KB, and 31 64KB sectors */
  199. #define Am29DL161DT_FLASH 0x0136 /* 8 8KB, and 31 64KB sectors */
  200. #define Am29DL161DB_FLASH 0x0139 /* 8 8KB, and 31 64KB sectors */
  201. #define Am29DL162DT_FLASH 0x012d /* 8 8KB, and 31 64KB sectors */
  202. #define Am29DL162DB_FLASH 0x012e /* 8 8KB, and 31 64KB sectors */
  203. #define Am29DL163DT_FLASH 0x0128 /* 8 8KB, and 31 64KB sectors */
  204. #define Am29DL163DB_FLASH 0x012b /* 8 8KB, and 31 64KB sectors */
  205. #define Am29DL164DT_FLASH 0x0133 /* 8 8KB, and 31 64KB sectors */
  206. #define Am29DL164DB_FLASH 0x0135 /* 8 8KB, and 31 64KB sectors */
  207. /* The DL32xG series has the same JEDEC IDs and sector architecture */
  208. #define Am29LV320DT_FLASH 0x01f6 /* 8 8KB, and 63 64KB sectors */
  209. #define Am29LV320DB_FLASH 0x01f9 /* 8 8KB, and 63 64KB sectors */
  210. #define Am29DL322DT_FLASH 0x0155 /* 8 8KB, and 63 64KB sectors */
  211. #define Am29DL322DB_FLASH 0x0156 /* 8 8KB, and 63 64KB sectors */
  212. #define Am29DL323DT_FLASH 0x0150 /* 8 8KB, and 63 64KB sectors */
  213. #define Am29DL323DB_FLASH 0x0153 /* 8 8KB, and 63 64KB sectors */
  214. #define Am29DL324DT_FLASH 0x015c /* 8 8KB, and 63 64KB sectors */
  215. #define Am29DL324DB_FLASH 0x015f /* 8 8KB, and 63 64KB sectors */
  216. #define Am29LV017D_FLASH        0x01c8 /* 32  64KB sectors */
  217. #define Am29LV033C_FLASH        0x01a3 /* 64  64KB sectors */
  218. #define Am29LV065D_FLASH        0x0193 /* 128 64KB sectors */
  219. #define Am29LV116DT_FLASH 0x01c7 /* 31 64KB, 1 32KB, 2 8KB, and 1 16KB 
  220.   sectors */
  221. #define Am29LV116DB_FLASH       0x014c /* 1 16KB, 2 8KB, 1 32KB, and 31 64KB 
  222.   sectors */
  223. #define Am29LV640D_FLASH 0x01d7 /* 128 64KB sectors */
  224. /* left out PDL series because of the double CE# lines and left out PDL 
  225.  * series since they are quite impractical WRT TrueFFS. Should add support
  226.  * for mirror bit devices as soon as data sheets become available.
  227.  */
  228. /* 5.0 volt devices */
  229. #define Am29F016D_FLASH 0x01ad /* 32 64KB uniform sectors */
  230. #define Am29F017D_FLASH 0x013d /* 32 64KB uniform sectors */
  231. #define Am29F160DT_FLASH 0x01d2 /* 31 64KB, 1 32KB, 2 8KB, and 1 16KB sectors */
  232. #define Am29F160DB_FLASH 0x01d8 /* 1 16KB, 2 8KB, 1 32KB, and 31 64KB sectors */
  233. #define Fuj29LV160TE_FLASH      0x04c4 /* 31 64KB, 1 32KB, 2 8KB, and 1 16KB sectors */
  234. #define Fuj29LV160BE_FLASH      0x0449 /* 1 16KB, 2 8KB, 1 32KB, and 31 64KB sectors */
  235. /******************************************************************************
  236.  * cfiAmdChipCountGet - return the number of chips in this array
  237.  *
  238.  * Leave the first chip (or set of interleaved chips) in READ_ARRAY
  239.  * mode and move forward by chip size (or interleaved chip size) until
  240.  * address wrap around is detected. The chip count is updated in 
  241.  * vol.noOfChips.
  242.  *
  243.  * NOMANUAL
  244.  *
  245.  */
  246. LOCAL FLStatus cfiAmdChipCountGet
  247.     (
  248.     FLFlash vol
  249.     )
  250.     {
  251.     UINT32 cmdBuffer;
  252.     int ix;
  253.     char queryIdStr[ID_STR_LENGTH + 1] = QUERY_ID_STR;
  254.     FlashPTR flashPtr = (FlashPTR) flMap(vol.socket, 0);
  255.     /* Switch first (interleaved) chip set to QUERY mode */
  256.     cmdBuffer = 0x0;
  257.     for (ix = 0; ix < thisCFI->multiplier; ix++)
  258. cmdBuffer |= QUERY << (8 * ix);
  259.     flashPtr[0x55 * thisCFI->multiplier] = cmdBuffer;
  260.     /* NOTE: The address wrap around technique used here works only if the flash
  261.      * size was declared correctly in the socket driver. At some point the MTD
  262.      * should be discovering flash size and exporting it to the socket driver. 
  263.      */
  264.     for (vol.noOfChips = 1 * vol.interleaving;       /* Scan the chips */
  265.          vol.noOfChips < 2000;  /* Big enough ? */
  266.          vol.noOfChips += vol.interleaving) 
  267.         {
  268. #ifdef SAVE_NVRAM_REGION
  269. /* Reinstate the NVRAM region */
  270. flashPtr = (FlashPTR) flMap(vol.socket, vol.noOfChips * 
  271. (vol.chipSize + (vol.erasableBlockSize / vol.interleaving)));
  272. #else
  273. flashPtr = (FlashPTR) flMap(vol.socket, vol.noOfChips * vol.chipSize);
  274. #endif
  275. #ifdef DEBUG_PRINT
  276. DEBUG_PRINT("Debug: Looking for Flash device at base 0x%xn", (UINT32) flashPtr);
  277. #endif
  278. if ((flashPtr[0x10 * thisCFI->multiplier]) 
  279.     == (unsigned char)queryIdStr[0] &&
  280.     (flashPtr[0x11 * thisCFI->multiplier]) 
  281.     == (unsigned char)queryIdStr[1] &&
  282.     (flashPtr[0x12 * thisCFI->multiplier]) 
  283.     == (unsigned char)queryIdStr[2])
  284.     {
  285.     goto noMoreChips;      /* Wrapped around */
  286.     }
  287. /* Confirm this is also a CFI part */
  288. *(UCHAR *)(flashPtr + (0x55 * thisCFI->multiplier))
  289.    = (UCHAR)(QUERY);
  290. if (flashPtr[0x10 * thisCFI->multiplier]
  291. != (unsigned char)queryIdStr[0] ||
  292.     flashPtr[0x11 * thisCFI->multiplier]
  293. != (unsigned char)queryIdStr[1] ||
  294.     flashPtr[0x12 * thisCFI->multiplier]
  295. != (unsigned char)queryIdStr[2])
  296.     {
  297.     /* Should not happen !! */
  298.     goto noMoreChips; /* Not a CFI Flash part */
  299.     }
  300. flashPtr[0x55 * thisCFI->multiplier] 
  301. = (UCHAR)(AMD_READ_ARRAY);
  302. }
  303.     /* We should never get here. */
  304. #ifdef DEBUG_PRINT
  305.     DEBUG_PRINT("Debug: Device count overflown");
  306. #endif  /* DEBUG_PRINT */
  307.     return flGeneralFailure;
  308.     
  309. noMoreChips:
  310.     flashPtr = (FlashPTR) flMap(vol.socket, 0);
  311.     /* Switch to READ_ARRAY mode */
  312.     cmdBuffer = 0x0;
  313.     for (ix = 0; ix < thisCFI->multiplier; ix++)
  314. cmdBuffer |= AMD_READ_ARRAY << (8 * ix);
  315.     flashPtr[0x55 * thisCFI->multiplier] = cmdBuffer;
  316.     return flOK;
  317.     }
  318. #if 0
  319. /******************************************************************************
  320.  * cfiAmdLeftoverBytesWrite - Write trailing bytes from aligned write
  321.  * 
  322.  * This is a helper routine to cfiAmdWrite(), which writes in chunks, 1, 2, and
  323.  * 4 bytes wide. The trailing bytes are written from here bye reading 4 bytes 
  324.  * from flash and OR-ing in the data to be written. Note that when programming 
  325.  * flash, a 1 can be tuned to 0 but a 0 cannot be turned to 1.
  326.  */
  327. LOCAL void cfiAmdLeftoverBytesWrite
  328.     (
  329.     FLFlash vol,
  330.     const void FAR1 *buffer,
  331.     FlashPTR flashPtr,
  332.     int length
  333.     )
  334.     {
  335.     /* data is a 1's mask, so we only try overwriting the
  336.      * bytes we desire ie. written a 1 should not change
  337.      * the state of an erase bit 
  338.      */
  339.     int byteCount;
  340.     ULONG data = 0xffffffff;
  341.     /* clear out the bytes we are going to overwrite */
  342.     for(byteCount = 0; byteCount<length; byteCount++)
  343.         data &= ~(0xff << (byteCount*8));
  344.     /* set the bits we dont want to clear in our data */
  345.     data |= CFI_LONGSWAP(* (ULONG *) buffer);
  346.     }
  347. #endif
  348. /******************************************************************************
  349.  * cfiAmdWrite - Write a block of bytes to Flash
  350.  *
  351.  * This routine will be registered as the MTD vol.write routine. Given a pointer 
  352.  * to a buffer that must be written, the write width determined from the 
  353.  * identification process is used the stepping stone to interate through the buffer.
  354.  *
  355.  * Parameters:                                         
  356.  * vol : Pointer identifying drive
  357.  *      address : Card address to write to
  358.  *      buffer : Address of data to write
  359.  * length : Number of bytes to write
  360.  * overwrite : TRUE if overwriting old Flash contents
  361.  *   FALSE if old contents are known to be erased
  362.  *                                                                     
  363.  * Returns:                                                           
  364.  * FLStatus : 0 on success, failed otherwise
  365.  */
  366. LOCAL FLStatus cfiAmdWrite
  367.     (
  368.     FLFlash vol,
  369.     CardAddress address,
  370.     const void FAR1 *buffer,
  371.     int length,
  372.     FLBoolean overwrite
  373.     )
  374.     {
  375.     /* Set timeout to 5 seconds from now */
  376.     unsigned long writeTimeout = flMsecCounter + 5000;
  377.     int cLength;
  378.     CardAddress cAddr = address;
  379.     FlashPTR base;
  380.     FlashPTR flashPtr;
  381.     UINT32 unlock1 = 0;
  382.     UINT32 unlock2 = 0;
  383.     UINT32 setup_write = 0;
  384.     UINT32 read_array = 0;
  385.     int i;
  386.     CFI_DWORD tmpDWord;
  387.     CFI_WORD  tmpWord;
  388. #define bFlashPtr  flashPtr
  389. #define bBuffer ((const unsigned char FAR1 *) buffer)
  390. #define wFlashPtr ((FlashWPTR) flashPtr)
  391. #define wBuffer ((const unsigned short FAR1 *) buffer)
  392. #define dFlashPtr ((FlashDPTR) flashPtr)
  393. #define dBuffer ((const unsigned long FAR1 *) buffer)
  394.     /* Setup the commands first */
  395.     for (i = 0; i < thisCFI->multiplier; i++)
  396. {
  397. unlock1  |= AMD_UNLOCK_1 << (i * 8);
  398. unlock2  |= AMD_UNLOCK_2 << (i * 8);
  399. setup_write |= AMD_SETUP_WRITE << (i * 8);
  400. read_array |= AMD_READ_ARRAY << (i * 8);
  401. }
  402.     if (flWriteProtected(vol.socket))
  403. return flWriteProtect;
  404.     i = 0; 
  405.     while ((thisCFI->secInfo[i].sectorBaseAdrs <= address) && (i < thisCFI->sectorsInCFI))
  406. i++;
  407.     i--;
  408.     base = (FlashPTR)
  409.   vol.map(&vol, thisCFI->secInfo[i].sectorBaseAdrs,
  410.     vol.interleaving * thisCFI->interleaveWidth);
  411.     flashPtr = (FlashPTR)
  412.   vol.map(&vol, address,
  413.     vol.interleaving * thisCFI->interleaveWidth);
  414.     cLength = length;
  415.     if (vol.interleaving * thisCFI->interleaveWidth == 1) 
  416. {
  417.         while (cLength >= 1) 
  418.        {
  419.     *(UCHAR *)(base + 
  420. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = unlock1;
  421.          *(UCHAR *)(base + 
  422. (thisCFI->unlockAddr2 * thisCFI->multiplier)) = unlock2;
  423.          *(UCHAR *)(base + 
  424. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = setup_write;
  425.     *bFlashPtr = *bBuffer;
  426.     while (bFlashPtr[0] != bBuffer[0] && flMsecCounter < writeTimeout) 
  427.         {
  428.         if ((bFlashPtr[0] & AMD_D5) && bFlashPtr[0] != bBuffer[0]) 
  429.     {
  430.     bFlashPtr[0] = read_array;
  431. #ifdef DEBUG_PRINT
  432.     DEBUG_PRINT("Debug: write failed in AMD MTD.n");
  433. #endif
  434.     return flWriteFault;
  435.     }
  436.         }
  437.     cLength--;
  438.     cAddr++;
  439.     buffer++;
  440.     bFlashPtr++;
  441.     }
  442.         }
  443.     else if (vol.interleaving * thisCFI->interleaveWidth == 2)  
  444. {
  445. while (cLength >= 2) 
  446.     {
  447.     *(USHORT *)(base + 
  448. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = unlock1;
  449.          *(USHORT *)(base + 
  450. (thisCFI->unlockAddr2 * thisCFI->multiplier)) = unlock2;
  451.          *(USHORT *)(base + 
  452. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = setup_write;
  453.     *wFlashPtr = *wBuffer;
  454.     while ((wFlashPtr[0] != wBuffer[0]) && 
  455.     (flMsecCounter < writeTimeout))
  456. {
  457. if (((wFlashPtr[0] & AMD_D5) && 
  458.     ((wFlashPtr[0] ^ wBuffer[0]) &   0xff)) ||
  459.     ((wFlashPtr[0] & (AMD_D5 * 0x100)) 
  460.      && ((wFlashPtr[0] ^ wBuffer[0]) & 0xff00))) 
  461.     {
  462.     wFlashPtr[0] = read_array;
  463. #ifdef DEBUG_PRINT
  464.             DEBUG_PRINT("Debug: write failed in AMD MTD.n");
  465. #endif
  466.     return flWriteFault;
  467.     }
  468. }
  469.     cLength -= 2;
  470.     cAddr += 2;
  471.     buffer += 2;
  472.     flashPtr += 2;
  473.     }
  474. if (cLength > 0)
  475.             {
  476.     /* copy data from flash to tmpWord */
  477.     tmpWord.ushort = wFlashPtr[0];
  478.     /* now fill in the left over byte */
  479.     tmpWord.uchar[0] = *(char *)buffer;
  480.     *(USHORT *)(base + 
  481. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = unlock1;
  482.          *(USHORT *)(base + 
  483. (thisCFI->unlockAddr2 * thisCFI->multiplier)) = unlock2;
  484.          *(USHORT *)(base + 
  485. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = setup_write;
  486.     *wFlashPtr = tmpWord.ushort;
  487.  
  488.     while ((wFlashPtr[0] != tmpWord.ushort) && 
  489.     (flMsecCounter < writeTimeout))
  490. {
  491. if (((wFlashPtr[0] & AMD_D5) && 
  492.     ((wFlashPtr[0] ^ tmpWord.ushort) &   0xff)) ||
  493.     ((wFlashPtr[0] & (AMD_D5 * 0x100)) 
  494.      && ((wFlashPtr[0] ^ tmpWord.ushort) & 0xff00))) 
  495.     {
  496.     wFlashPtr[0] = read_array;
  497. #ifdef DEBUG_PRINT
  498.             DEBUG_PRINT("Debug: write failed in AMD MTD.n");
  499. #endif
  500.     return flWriteFault;
  501.     }
  502. }
  503.     cAddr += cLength;
  504.     buffer += cLength;
  505.     flashPtr += cLength;
  506.     cLength = 0;
  507.     }
  508.     /* cfiAmdLeftoverBytesWrite(&vol, buffer, flashPtr, cLength); */
  509. }
  510.     else /* if (vol.interleaving >= 4) */ 
  511. {
  512. while (cLength >= 4) 
  513.     {
  514.     *(UINT32 *)(base + 
  515. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = unlock1;
  516.          *(UINT32 *)(base + 
  517. (thisCFI->unlockAddr2 * thisCFI->multiplier)) = unlock2;
  518.          *(UINT32 *)(base + 
  519. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = setup_write;
  520.     *dFlashPtr = *dBuffer;
  521.     while ((dFlashPtr[0] != dBuffer[0]) && 
  522.     (flMsecCounter < writeTimeout)) 
  523. {
  524. if (thisCFI-> interleaveWidth == 1)
  525.     {
  526.     /* We have 4 8 bit devices */
  527.     if (((dFlashPtr[0] & AMD_D5) && 
  528. ((dFlashPtr[0] ^ dBuffer[0]) & 0xff)) ||
  529. ((dFlashPtr[0] & (AMD_D5 * 0x100)) && 
  530. ((dFlashPtr[0] ^ dBuffer[0]) & 0xff00)) ||
  531. ((dFlashPtr[0] & (AMD_D5 * 0x10000lu)) && 
  532. ((dFlashPtr[0] ^ dBuffer[0]) & 0xff0000lu)) ||
  533. ((dFlashPtr[0] & (AMD_D5 * 0x1000000lu)) && 
  534. ((dFlashPtr[0] ^ dBuffer[0]) & 0xff000000lu))) 
  535.         {
  536. #ifdef DEBUG_PRINT
  537.   DEBUG_PRINT("Debug: write failed in AMD MTD.n");
  538. #endif
  539.         dFlashPtr[0] = read_array;
  540.         return flWriteFault;
  541.         }
  542.     }
  543. else
  544.     {
  545.     /* Here we assume that the only other option is 2 16 bit devices */
  546.     if (((dFlashPtr[0] & AMD_D5) && 
  547. ((dFlashPtr[0] ^ dBuffer[0]) & 0x0000ffff)) ||
  548.         ((dFlashPtr[0] & (AMD_D5 * 0x10000lu)) && 
  549. ((dFlashPtr[0] ^ dBuffer[0]) & 0xffff0000)))
  550. {
  551. #ifdef DEBUG_PRINT
  552.   DEBUG_PRINT("Debug4-1: write failed in AMD MTD.n");
  553. #endif
  554.         dFlashPtr[0] = read_array;
  555.         return flWriteFault;
  556.         }
  557.     }     
  558. }
  559.     cLength -= 4;
  560.     cAddr += 4;
  561.     buffer += 4;
  562.     flashPtr += 4;
  563.     }
  564. if (cLength > 0)
  565.             {
  566.     tmpDWord.uint32 = 0xffffffff;
  567.     /* read trailing bytes in to temp dword */
  568.     for (i = 0; i < cLength; i++)
  569. tmpDWord.uchar[i] = *((char *)buffer + i);
  570.     /* fill the rest from flash */
  571.     for (    ; i < 4; i++)
  572. tmpDWord.uchar[i] = *(flashPtr + i);
  573.     *(UINT32 *)(base + 
  574. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = unlock1;
  575.          *(UINT32 *)(base + 
  576. (thisCFI->unlockAddr2 * thisCFI->multiplier)) = unlock2;
  577.          *(UINT32 *)(base + 
  578. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = setup_write;
  579.     *dFlashPtr = tmpDWord.uint32;
  580.     while ((dFlashPtr[0] != tmpDWord.uint32) && 
  581.     (flMsecCounter < writeTimeout)) 
  582. {
  583. if (thisCFI-> interleaveWidth == 1)
  584.     {
  585.     /* We have 4 8 bit devices */
  586.     if (((dFlashPtr[0] & AMD_D5) && 
  587. ((dFlashPtr[0] ^ tmpDWord.uint32) & 0xff)) ||
  588. ((dFlashPtr[0] & (AMD_D5 * 0x100)) && 
  589. ((dFlashPtr[0] ^ tmpDWord.uint32) & 0xff00)) ||
  590. ((dFlashPtr[0] & (AMD_D5 * 0x10000lu)) && 
  591. ((dFlashPtr[0] ^ tmpDWord.uint32) & 0xff0000lu)) ||
  592. ((dFlashPtr[0] & (AMD_D5 * 0x1000000lu)) && 
  593. ((dFlashPtr[0] ^ tmpDWord.uint32) & 0xff000000lu))) 
  594.         {
  595. #ifdef DEBUG_PRINT
  596.   DEBUG_PRINT("Debug: write failed in AMD MTD.n");
  597. #endif
  598.         dFlashPtr[0] = read_array;
  599.         return flWriteFault;
  600.         }
  601.     }
  602. else
  603.     {
  604.     /* Here we assume that the only other option is 16 devices */
  605.     if (((dFlashPtr[0] & AMD_D5) && 
  606. ((dFlashPtr[0] ^ tmpDWord.uint32) & 0x0000ffff)) ||
  607.         ((dFlashPtr[0] & (AMD_D5 * 0x10000lu)) && 
  608. ((dFlashPtr[0] ^ tmpDWord.uint32) & 0xffff0000)))
  609. {
  610. #ifdef DEBUG_PRINT
  611.   DEBUG_PRINT("Debug4-2: write failed in AMD MTD.n");
  612. #endif
  613.         dFlashPtr[0] = read_array;
  614.         return flWriteFault;
  615.         }
  616.     }     
  617. }
  618.     cAddr += cLength;
  619.     buffer += cLength;
  620.     flashPtr += cLength;
  621.     cLength = 0;
  622.     }
  623.     /* cfiAmdLeftoverBytesWrite(&vol, buffer, flashPtr, cLength); */
  624. }
  625.     flashPtr -= length;
  626.     buffer = (unsigned char *)buffer - length; /* bBuffer -= length; */
  627.     if (tffscmp((void FAR0 *) flashPtr,buffer,length)) 
  628. {
  629. #ifdef DEBUG_PRINT
  630. DEBUG_PRINT("Debug: write failed in AMD MTD on verification.n");
  631. #endif
  632. return flWriteFault;
  633. }
  634.     return flOK;
  635.     }
  636. /*******************************************************************************
  637.  * cfiAmdBootBlockErase - Erase sub blocks within boot block
  638.  *
  639.  * Use the boot block data discovered at CFI interrogation time and erase all 
  640.  * subsectors in the boot block.
  641.  *
  642.  * Parameters:                                         
  643.  * vol : Pointer identifying drive
  644.  *      firstErasableBlock : Sector number of start of boot block
  645.  *                                                             
  646.  * Returns:                                                   
  647.  * FLStatus : 0 on success, failed otherwise
  648.  */
  649. LOCAL FLStatus cfiAmdBootBlockErase
  650.     (
  651.     FLFlash vol,
  652.     int firstErasableBlock
  653.     )
  654.     {
  655.     int iBlock, i;
  656.     UINT32 unlock1 = 0;
  657.     UINT32 unlock2 = 0;
  658.     UINT32 erase_setup = 0;
  659.     UINT32 erase_sector = 0;
  660.     /* Setup the commands first */
  661.     for (i = 0; i < thisCFI->multiplier; i++)
  662. {
  663. unlock1  |= AMD_UNLOCK_1 << (i * 8);
  664. unlock2  |= AMD_UNLOCK_2 << (i * 8);
  665. erase_setup |= AMD_SETUP_ERASE << (i * 8);
  666. erase_sector  |= AMD_SECTOR_ERASE << (i * 8);
  667. }
  668.     for (iBlock = firstErasableBlock; 
  669. (iBlock - firstErasableBlock) < thisCFI->bootBlockSectors; 
  670. iBlock++) 
  671. {
  672. int i;
  673. FLBoolean finished;
  674. FlashPTR flashPtr;
  675. /* No need to call mapBase because we know we are on 
  676.  * a unit boundary 
  677.  */
  678. flashPtr = (FlashPTR)
  679.   vol.map(&vol, thisCFI->secInfo[iBlock].sectorBaseAdrs, 0);
  680.      *(UINT32 *)(flashPtr + 
  681. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = unlock1;
  682.      *(UINT32 *)(flashPtr + 
  683. (thisCFI->unlockAddr2 * thisCFI->multiplier)) = unlock2;
  684.      *(UINT32 *)(flashPtr + 
  685. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = erase_setup;
  686.      *(UINT32 *)(flashPtr + 
  687. (thisCFI->unlockAddr1 * thisCFI->multiplier)) = unlock1;
  688.      *(UINT32 *)(flashPtr + 
  689. (thisCFI->unlockAddr2 * thisCFI->multiplier)) = unlock2;
  690.      *(UINT32 *)flashPtr = erase_sector;
  691. do 
  692.     {
  693.     finished = TRUE;
  694.     for (i = 0;i < thisCFI->multiplier;i += thisCFI->interleaveWidth) 
  695. {
  696. if (flashPtr[i] != 0xff) 
  697.     {
  698.     if ((flashPtr[i] & AMD_D5) && flashPtr[i] != 0xff) 
  699. {
  700. flashPtr[i] = AMD_READ_ARRAY;
  701. #ifdef DEBUG_PRINT
  702.      DEBUG_PRINT("Debug: erase failed in AMD MTD.n");
  703. #endif
  704. return flWriteFault;
  705. }
  706.     finished = FALSE;
  707.     }
  708. }
  709.     } while (!finished);
  710. }
  711.     return flOK;
  712.     }
  713. /*******************************************************************************
  714.  * cfiAmdErase - Erase one or more contiguous Flash erasable blocks
  715.  *
  716.  * This routine will be registered as the MTD vol.erase routine. Sector zero is 
  717.  * assumed to be the boot block anchor of the boot block on bottom boot devices,
  718.  * while the first sector of size not equal to vol.erasableBlockSize is assumed 
  719.  * to be the anchor for top boot devices.
  720.  *
  721.  * Parameters:                                         
  722.  * vol : Pointer identifying drive
  723.  *      firstErasableBlock : Number of first block to erase
  724.  * numOfErasableBlocks: Number of blocks to erase
  725.  *                                                             
  726.  * Returns:                                                   
  727.  * FLStatus : 0 on success, failed otherwise
  728.  */
  729. LOCAL  FLStatus cfiAmdErase
  730.     (
  731.     FLFlash vol,
  732.     int firstErasableBlock,
  733.     int numOfErasableBlocks
  734.     )
  735.     {
  736.     int i;
  737.     UINT32 unlock1 = 0;
  738.     UINT32 unlock2 = 0;
  739.     UINT32 erase_setup = 0;
  740.     UINT32 erase_sector = 0;
  741.     int thisSector = firstErasableBlock;
  742.     int sectorsToErase = numOfErasableBlocks;
  743.     UINT32 * unlockAddr1;
  744.     UINT32 * unlockAddr2;
  745.     if (flWriteProtected(vol.socket))
  746. return flWriteProtect;
  747.     if ((thisCFI->bootBlockType == BOOTBLOCK_BOTTOM) && 
  748.      (firstErasableBlock == 0))
  749. {
  750. #ifdef DEBUG_PRINT
  751. DEBUG_PRINT("Debug: Erasing bottom boot blockn");
  752. #endif
  753.     cfiAmdBootBlockErase(&vol, 0);
  754.     thisSector += thisCFI->bootBlockSectors;
  755. }
  756. /* Setup the commands first */
  757.     for (i = 0; i < thisCFI->multiplier; i++)
  758. {
  759. unlock1   |= AMD_UNLOCK_1 << (i * 8);
  760. unlock2   |= AMD_UNLOCK_2 << (i * 8);
  761. erase_setup  |= AMD_SETUP_ERASE << (i * 8);
  762. erase_sector |= AMD_SECTOR_ERASE << (i * 8);
  763. }
  764.     
  765.     for ( ; thisSector < firstErasableBlock + sectorsToErase; thisSector++) 
  766. {
  767. int i;
  768. FLBoolean finished;
  769. FlashPTR flashPtr;
  770. /* Check if we have hit a boot block region on a top 
  771.  * boot device. If so lets clean it up and move on with 
  772.  * the others
  773.  */
  774. if ((thisCFI->bootBlockType == BOOTBLOCK_TOP) &&
  775. (thisCFI->secInfo[thisSector].sectorSize != vol.erasableBlockSize))
  776.     {
  777. #ifdef DEBUG_PRINT
  778. DEBUG_PRINT("Debug: Erasing top boot blockn");
  779. #endif
  780.     cfiAmdBootBlockErase(&vol, thisSector);
  781.     break;
  782.     }
  783. #ifdef DEBUG_PRINT 
  784. DEBUG_PRINT("Clearing sector %dn", thisSector);
  785. #endif 
  786. /* we know we are on a unit boundary so mapBase is not necessary */
  787. flashPtr = (FlashPTR)
  788.   vol.map(&vol, thisCFI->secInfo[thisSector].sectorBaseAdrs, 0);
  789. unlockAddr1 = (UINT32 *)((long)flashPtr + (thisCFI->unlockAddr1 *thisCFI->multiplier));
  790. unlockAddr2 = (UINT32 *)((long)flashPtr + (thisCFI->unlockAddr2 *thisCFI->multiplier));
  791.     *unlockAddr1 = unlock1;
  792.      *unlockAddr2 = unlock2;
  793. *unlockAddr1 = erase_setup;
  794.      *unlockAddr1 = unlock1;
  795.      *unlockAddr2 = unlock2;
  796.      *(UINT32 *)flashPtr = erase_sector;
  797. do 
  798.     {
  799.     finished = TRUE;
  800.     for (i = 0;i < thisCFI->multiplier;i += thisCFI->interleaveWidth) 
  801. {
  802. if (flashPtr[i] != 0xff) 
  803.     {
  804.     if ((flashPtr[i] & AMD_D5) && flashPtr[i] != 0xff) 
  805. {
  806. int x;
  807. UINT32 c;
  808. for (x = 0, c = 0; x < thisCFI->multiplier; x++)
  809.          c |= AMD_READ_ARRAY << (x * 8);
  810. flashPtr[i] = c;
  811. #ifdef DEBUG_PRINT
  812.     DEBUG_PRINT("Debug: erase failed in AMD MTD.n");
  813. #endif
  814. return flWriteFault;
  815. }
  816.     finished = FALSE;
  817.     }
  818. }
  819.     } while (!finished);
  820. }
  821.     return flOK;
  822.     }
  823. /***************************************************************************
  824.  * cfiscsIdentify - Identification routine for devices conforming to CFI/SC
  825.  *
  826.  * Identifies media based on CFI and the AMD/Fujitsu command set and registers
  827.  * as an MTD for such. This routine should be placed on the MTD list in flcustom.h.
  828.  * It must be an extern routine. On successful identification, the Flash 
  829.  * structure is filled out and the write and erase routines registered. 
  830.  *
  831.  * Parameters:
  832.  *      vol             : Pointer identifying drive 
  833.  *
  834.  * Returns:
  835.  *      FLStatus        : 0 on positive identificaion, failed otherwise 
  836.  *
  837.  * http://www.amd.com/us-en/FlashMemory/ProductInformation/0,,37_1447_1451_1780%5E1834%5E1955,00.html
  838.  *
  839.  *
  840.  * NOMANUAL
  841.  *
  842.  */
  843. FLStatus cfiAmdIdentify
  844.     (
  845.     FLFlash vol
  846.     )
  847.     {
  848.     FlashPTR flashPtr = (FlashPTR) flMap(vol.socket, 0);
  849.     FlashWPTR flashWPtr = (FlashWPTR) flashPtr;
  850.     FlashDPTR flashDPtr = (FlashDPTR) flashPtr;
  851.     UINT32 unlock1 = 0;
  852.     UINT32 unlock2 = 0;
  853.     UINT32 readID = 0;
  854.     UINT32 readArray = 0;
  855.     int i;
  856.    unsigned primaryTable, secondaryTable;
  857.     FLBoolean eightBitMode = FALSE;
  858.     int thisSector = 0; /* running count of sectors for this CFI */
  859.     CardAddress sectorBaseAdrs = 0; /* base address of this sector */
  860.     int ix = 0;
  861. #ifdef DEBUG_PRINT
  862.     DEBUG_PRINT("Debug: entering CFIAMD identification routine.n");
  863. #endif
  864.     flSetWindowBusWidth(vol.socket, 16);/* use 16-bits */
  865.     flSetWindowSpeed(vol.socket, 120);  /* 120 nsec. */
  866.     flSetWindowSize(vol.socket, 2);       /* 8 KBytes */
  867.     vol.mtdVars = &mtdVars[flSocketNoOf(vol.socket)];
  868.     thisCFI->bootBlockSectors = 0;
  869.     /* Is this an 8 bit device */
  870.     flashPtr[0x55] = AMD_READ_ARRAY;
  871.     flashPtr[0x55] = QUERY;
  872.     
  873.     if (flashPtr[0x10] == 0x51 && /* 'Q' */
  874.         flashPtr[0x11] == 0x52 && /* 'R' */
  875.         flashPtr[0x12] == 0x59)   /* 'Y' */
  876.         {
  877. #ifdef DEBUG_PRINT
  878.         DEBUG_PRINT ("Debug: detected single 8 bit devicen");
  879. #endif
  880.         thisCFI->multiplier = 1;
  881. thisCFI->interleaveWidth = 1;
  882.         vol.interleaving = 1;
  883. eightBitMode = TRUE;
  884.         goto getCFI;
  885.         }
  886.     /* Reset to READ_ARRAY and retry. Maybe 16 bit addressing 
  887.      */
  888.     flashPtr[0x55] = AMD_READ_ARRAY;
  889.     flashWPtr[0x55] = (USHORT) ((QUERY << 8) | QUERY); 
  890.     /* Check for two interleaved 8 bit parts */
  891.     if (flashPtr[0x20] == 0x51 && /* 'Q' */
  892.         flashPtr[0x21] == 0x51 && /* 'Q' */
  893.         flashPtr[0x22] == 0x52 && /* 'R' */
  894.         flashPtr[0x23] == 0x52 && /* 'R' */
  895.         flashPtr[0x24] == 0x59 && /* 'Y' */
  896.         flashPtr[0x25] == 0x59)   /* 'Y' */
  897.      {
  898. /* Let's try turning one off */
  899. CFI_WORD_WRITE((FlashWPTR)(&flashPtr[0x55]), AMD_READ_ARRAY);
  900. if (flashPtr[0x20] != 0x51) /* Turned off successfully */
  901.     {
  902.     thisCFI->multiplier = 2;
  903.     thisCFI->interleaveWidth = 1;
  904.     vol.interleaving =2;
  905. #ifdef DEBUG_PRINT
  906.     DEBUG_PRINT ("Debug: detected two 8 bit devicesn");
  907. #endif
  908.     eightBitMode = TRUE;
  909.     goto getCFI;
  910.     }
  911. }
  912.     /* a 16 bit device in 16 bit mode */
  913.     if (flashWPtr[0x10] == 'Q' && 
  914.         flashWPtr[0x11] == 'R' &&
  915.         flashWPtr[0x12] == 'Y')
  916.         {
  917.         thisCFI->multiplier = 2;
  918. thisCFI->interleaveWidth = 1;
  919. vol.interleaving = 1;
  920. #ifdef DEBUG_PRINT
  921.         DEBUG_PRINT ("Debug: detected one 16 bit devicen");
  922. #endif
  923. goto getCFI;
  924. }
  925.     /* If we have a 16 bit device in 8 bit mode it should ID correctly */
  926.     if (flashPtr[0x20] == 0x51 && /* 'Q' */
  927.         flashPtr[0x21] == 0x51 && /* 'Q' */
  928.         flashPtr[0x22] == 0x52 && /* 'R' */
  929.         flashPtr[0x23] == 0x52 && /* 'R' */
  930.         flashPtr[0x24] == 0x59 && /* 'Y' */
  931.         flashPtr[0x25] == 0x59)   /* 'Y' */
  932.         {
  933. thisCFI->multiplier = 2;
  934. #ifdef DEBUG_PRINT
  935.         DEBUG_PRINT ("Debug: detected a 16 bit device in 8 bit moden");
  936. #endif
  937.      vol.interleaving =1;
  938. thisCFI->interleaveWidth = 1;
  939. eightBitMode = TRUE;
  940. goto getCFI;
  941.      }
  942.     /* Reset to READ_ARRAY and retry. Maybe 32 bit addressing 
  943.      */
  944.     flashWPtr[0x55] = (USHORT) ((AMD_READ_ARRAY << 8) | AMD_READ_ARRAY); 
  945.     flashDPtr[0x55] = (ULONG) (QUERY << 24| QUERY <<16 | QUERY << 8 | QUERY); 
  946.     /* A 32 bit device in 8 bit mode and two 16 bit deivec in 8 bit mode will
  947.      * appear the same to the querry process. The only way to make the
  948.      * distinction is to try and set one device back to read array mode while
  949.      * the other remains in query mode */
  950.     if (flashPtr[0x40] == 0x51 && /* 'Q' */
  951.         flashPtr[0x41] == 0x51 && /* 'Q' */
  952.         flashPtr[0x42] == 0x51 && /* 'Q' */
  953.         flashPtr[0x43] == 0x51 && /* 'Q' */
  954.         flashPtr[0x44] == 0x52 && /* 'R' */
  955.         flashPtr[0x45] == 0x52 && /* 'R' */
  956.         flashPtr[0x46] == 0x52 && /* 'R' */
  957.         flashPtr[0x47] == 0x52 && /* 'R' */
  958.         flashPtr[0x48] == 0x59 && /* 'Y' */
  959.         flashPtr[0x49] == 0x59 && /* 'Y' */
  960.         flashPtr[0x4a] == 0x59 && /* 'Y' */
  961.         flashPtr[0x4b] == 0x59)   /* 'Y' */
  962.         {
  963. /* See if we can turn one off */
  964. flashPtr[0x154] = AMD_READ_ARRAY;
  965. if ((flashPtr[0x40] != 0x51) && (flashPtr[0x41] == 0x51))
  966.     { /* Turned one device off successfully */
  967.     flashPtr[0x154] = QUERY;  /* turn it back on to querry mode */
  968.     vol.interleaving = 2;
  969. #ifdef DEBUG_PRINT
  970.     DEBUG_PRINT ("Debug: detected two 16 bit device, 8 bit interleaved(2)n");
  971. #endif
  972.     }
  973. else
  974.     {
  975.     vol.interleaving =1;
  976. #ifdef DEBUG_PRINT
  977.     DEBUG_PRINT ("Debug: detected a 32 bit device in 8 bit moden");
  978. #endif
  979.     }
  980.         thisCFI->multiplier = 4;
  981. thisCFI->interleaveWidth = 1;
  982. eightBitMode = TRUE;
  983. goto getCFI;
  984. }
  985.     /* Is it a single 32 bit device */
  986.     if (flashDPtr[0x10] == 'Q' &&
  987.         flashDPtr[0x11] == 'R' &&
  988.         flashDPtr[0x12] == 'Y')
  989.         {
  990. #ifdef DEBUG_PRINT
  991.         DEBUG_PRINT ("Debug: detected a 32 bit device in 32 bit moden");
  992. #endif
  993. thisCFI->multiplier = 4;
  994. thisCFI->interleaveWidth = 1;
  995. vol.interleaving = 1;
  996. goto getCFI;
  997. }
  998.     /* Two 16 bit devices in 16 bit mode */
  999.     if (flashWPtr[0x20] == 'Q' &&
  1000.         flashWPtr[0x21] == 'Q' &&
  1001.         flashWPtr[0x22] == 'R' &&
  1002.         flashWPtr[0x23] == 'R' &&
  1003.         flashWPtr[0x24] == 'Y' &&
  1004.         flashWPtr[0x25] == 'Y')
  1005.         {
  1006. #ifdef DEBUG_PRINT
  1007.         DEBUG_PRINT ("Debug: Detected two 16 bit devices in 16 bit mode(3)n");
  1008. #endif
  1009. thisCFI->multiplier = 4;
  1010. thisCFI->interleaveWidth = 2;
  1011. vol.interleaving = 2;
  1012. goto getCFI;
  1013. }
  1014.     /* If we get here the device is probably not CFI */
  1015. #ifdef DEBUG_PRINT
  1016.     DEBUG_PRINT ("Debug: Failed to identify CFI... n Exiting n");
  1017. #endif
  1018.     flashDPtr[0x55] = (ULONG) (AMD_READ_ARRAY << 24| AMD_READ_ARRAY <<16 
  1019.      | AMD_READ_ARRAY << 8 | AMD_READ_ARRAY); 
  1020.     return flUnknownMedia;
  1021. getCFI:
  1022.     if (!eightBitMode)
  1023. {
  1024. thisCFI->wordMode = TRUE; /* limitting ourselves to 8 an 16 bit devs */
  1025. thisCFI->unlockAddr1 = AMD_WW_UNLOCK_ADDR1;
  1026. thisCFI->unlockAddr2 = AMD_WW_UNLOCK_ADDR2;
  1027. #ifdef DEBUG_PRINT
  1028. DEBUG_PRINT("WORD MODE !!n");
  1029. #endif
  1030. }
  1031.     else
  1032. {
  1033. thisCFI->wordMode = FALSE;
  1034. thisCFI->unlockAddr1 = AMD_BW_UNLOCK_ADDR1;
  1035. thisCFI->unlockAddr2 = AMD_BW_UNLOCK_ADDR2;
  1036. #ifdef DEBUG_PRINT
  1037. DEBUG_PRINT("WORD MODE !!n");
  1038. #endif
  1039. }
  1040.     /* check the command set ID */
  1041.     /* NOTE: Not swapped */
  1042.     thisCFI->commandSetId = *(USHORT *)(&flashPtr[0x13 * thisCFI->multiplier]);
  1043. #ifdef DEBUG_PRINT
  1044.     DEBUG_PRINT ("Debug: Commandset ID is 0x%xn", thisCFI->commandSetId);
  1045. #endif
  1046.     /* Only support the AMD/Fujitsu Command set */
  1047.     if ( thisCFI->commandSetId != AMDFUJ_COMMAND_SET) 
  1048.         {
  1049. #ifdef DEBUG_PRINT
  1050.     DEBUG_PRINT("Debug: did not recognize command set.n");
  1051. #endif
  1052.         return flUnknownMedia;
  1053.         }
  1054.     /* get address for primary algorithm extended table. */
  1055.     primaryTable = CFI_WORD_READ(&flashPtr[0x15 * thisCFI->multiplier]);
  1056.     /* check alternate command set ID. */
  1057.     /* NOTE: not swapped */
  1058.     thisCFI->altCommandSetId = *(USHORT *)
  1059. (&flashPtr[0x17 * thisCFI->multiplier]);
  1060.     if (thisCFI->altCommandSetId != AMDFUJ_ALT_COMMAND_SET &&
  1061.         thisCFI->altCommandSetId != ALT_NOT_SUPPORTED)
  1062.         return flUnknownMedia;
  1063.     /* get address for secondary algorithm extended table. */
  1064.     secondaryTable = CFI_WORD_READ(&flashPtr[0x19 * thisCFI->multiplier]);
  1065.     thisCFI->vpp = flashPtr[0x1d * thisCFI->multiplier];
  1066.     /*Get the number of erase block descriptions for thei CFI*/
  1067.     if (eightBitMode)
  1068. thisCFI->sectorDefs = (int) (*(UCHAR *) 
  1069. (&flashPtr[0x2c * thisCFI->multiplier]));
  1070.     else
  1071. thisCFI->sectorDefs = (int) (*(USHORT *)
  1072.     (&flashPtr[0x2c * thisCFI->multiplier]));
  1073.     /* We should bail out if this is greater than 8 */
  1074. #ifdef DEBUG_PRINT
  1075.     DEBUG_PRINT ("Debug: Number of erase block descriptions is 0x%xn", 
  1076.     thisCFI->sectorDefs);
  1077. #endif
  1078.     vol.erasableBlockSize = 0;
  1079.     thisCFI->sectorsInCFI = 0;
  1080.     for ( ix = 0; ix < thisCFI->sectorDefs; ix++)
  1081. {
  1082. thisCFI->secDesc[ix].numSecs = (int) (*(USHORT *)
  1083. (&flashPtr[(0x2d + (ix * 4)) * thisCFI->multiplier]));
  1084. thisCFI->secDesc[ix].numSecs++;
  1085. #ifdef DEBUG_PRINT
  1086.     DEBUG_PRINT ("Debug: Num sectors in %d - %dn", ix, thisCFI->secDesc[ix].numSecs);
  1087. #endif
  1088. thisCFI->secDesc[ix].secSize = (long) ((*(USHORT *)
  1089. (&flashPtr[(0x2f + (ix * 4)) * thisCFI->multiplier])) +
  1090. (*(USHORT *)(&flashPtr[(0x30 + (ix * 4)) * 
  1091.        thisCFI->multiplier])) * 0x100L);
  1092. #ifdef DEBUG_PRINT
  1093.     DEBUG_PRINT ("Debug: Sector size is 0x%xn",
  1094. (UINT32) thisCFI->secDesc[ix].secSize);
  1095. #endif
  1096. /* TrueFFS does not support the flexible sector architecture so we 
  1097.  * take the largest sector size to be the erase block size.
  1098.  */ 
  1099. if (vol.erasableBlockSize < thisCFI->secDesc[ix].secSize)
  1100.     vol.erasableBlockSize = thisCFI->secDesc[ix].secSize;
  1101. /* Also track the number of sector on this device */
  1102. thisCFI->sectorsInCFI += thisCFI->secDesc[ix].numSecs;
  1103. }
  1104.     if (vol.erasableBlockSize == 0x00)
  1105. vol.erasableBlockSize = 0x80L;
  1106.     else
  1107. vol.erasableBlockSize *= 256;
  1108.     /* Get Device Size */
  1109.     if (eightBitMode)
  1110. vol.chipSize = (1L << flashPtr[0x27 * thisCFI->multiplier]);
  1111.     else
  1112. vol.chipSize = (1L << *(USHORT*)(&flashPtr[0x27 * thisCFI->multiplier]));
  1113.     vol.erasableBlockSize *= vol.interleaving;
  1114.     
  1115. #ifdef SAVE_NVRAM_REGION
  1116.     /* Top boot block devices will loose their entire boot block to NVRAM. Since 
  1117.      * TrueFFS cares not about the subdivisions we reserve an entire erase block
  1118.      * on each of the interleaved devices. 
  1119.      */
  1120.     vol.chipSize -= vol.erasableBlockSize;
  1121. #endif
  1122. #ifdef DEBUG_PRINT
  1123.     DEBUG_PRINT("Debug: %d sectors on devicen", thisCFI->sectorsInCFI);
  1124.     DEBUG_PRINT("Debug: Erasable block size is 0x%lxn", vol.erasableBlockSize);
  1125.     DEBUG_PRINT("Debug: Chip size is 0x%lxn", vol.chipSize);
  1126. #endif
  1127.     /* Since boot blocks happen to be subdevided erase blocks and TrueFFS does
  1128.      * not support the sub devision of erase blocks the MTD needs to be able
  1129.      * to detect the "sectors" that are sub devisions and erase all of them
  1130.      * (assuming that they are contiguous) together. Since the boot block can
  1131.      * appear either at the top or the bottom, the only way to keep track of
  1132.      * them is to read all sector descriptions and remember them for cross
  1133.      * reference. The size of the largest erase block is registered as the
  1134.      * eraseBlockSize for the volume.
  1135.      */
  1136.     /* Setup the commands first */
  1137.     for (i = 0; i < thisCFI->multiplier; i++)
  1138. {
  1139. unlock1   |= AMD_UNLOCK_1   << (i * 8);
  1140. unlock2   |= AMD_UNLOCK_2   << (i * 8);
  1141. readID    |= AMD_READ_ID    << (i * 8);
  1142. readArray   |= AMD_READ_ARRAY << (i * 8);
  1143. }
  1144.     
  1145.     /* Get JEDEC ID so we know if this is a top or bottom boot device */
  1146.     *(UINT32 *)(flashPtr + (thisCFI->unlockAddr1 * thisCFI->multiplier)) = unlock1;
  1147.     *(UINT32 *)(flashPtr + (thisCFI->unlockAddr2 * thisCFI->multiplier)) = unlock2;
  1148.     *(UINT32 *)(flashPtr + (thisCFI->unlockAddr1 * thisCFI->multiplier)) = readID;
  1149.     if (eightBitMode)
  1150.         vol.type = flashPtr[0] << 8 | flashPtr[thisCFI->interleaveWidth];
  1151.     else
  1152. vol.type = (*(USHORT *)(&flashPtr[0]) << 8) | 
  1153.     (*(USHORT *)(&flashPtr[thisCFI->multiplier]) & 0x00ff);
  1154.     /* Determine boot block type */
  1155.     if ((vol.type == Am29DS163DT_FLASH) ||
  1156. (vol.type == Am29DS323DT_FLASH) ||
  1157. (vol.type == Am29PDS322DT_FLASH)||
  1158. (vol.type == Am29SL160CT_FLASH) ||
  1159. (vol.type == Am29DL161DT_FLASH) ||
  1160. (vol.type == Am29DL162DT_FLASH) ||
  1161. (vol.type == Am29DL163DT_FLASH) ||
  1162. (vol.type == Am29DL164DT_FLASH) ||
  1163. (vol.type == Am29LV320DT_FLASH) ||
  1164. (vol.type == Am29DL322DT_FLASH) ||
  1165. (vol.type == Am29DL323DT_FLASH) ||
  1166. (vol.type == Am29DL324DT_FLASH) ||
  1167. (vol.type == Am29LV116DT_FLASH) ||
  1168. (vol.type == Am29F160DT_FLASH)  ||
  1169. (vol.type == Fuj29LV160TE_FLASH))
  1170. thisCFI->bootBlockType = BOOTBLOCK_TOP;
  1171.     else if ((vol.type == Am29DS163DT_FLASH) ||
  1172. (vol.type == Am29DS323DB_FLASH) ||
  1173. (vol.type == Am29PDS322DB_FLASH) ||
  1174. (vol.type == Am29SL160CB_FLASH) ||
  1175. (vol.type == Am29DL161DB_FLASH) ||
  1176. (vol.type == Am29DL162DB_FLASH) ||
  1177. (vol.type == Am29DL163DB_FLASH) ||
  1178. (vol.type == Am29DL164DB_FLASH) ||
  1179. (vol.type == Am29LV320DB_FLASH) ||
  1180. (vol.type == Am29DL322DB_FLASH) ||
  1181. (vol.type == Am29DL323DB_FLASH) ||
  1182. (vol.type == Am29DL324DB_FLASH) ||
  1183. (vol.type == Am29LV116DB_FLASH) ||
  1184. (vol.type == Am29F160DB_FLASH)  ||
  1185. (vol.type == Fuj29LV160BE_FLASH))
  1186. thisCFI->bootBlockType = BOOTBLOCK_BOTTOM;
  1187.     else if ((vol.type == Am29LV017D_FLASH) ||
  1188. (vol.type == Am29LV033C_FLASH) ||
  1189. (vol.type == Am29LV065D_FLASH) ||
  1190. (vol.type == Am29LV640D_FLASH) ||
  1191. (vol.type == Am29F016D_FLASH)  ||
  1192. (vol.type == Am29F017D_FLASH))
  1193. thisCFI->bootBlockType = BOOTBLOCK_NONE;
  1194.     else
  1195. {
  1196. /* Probably an unregistered device that needs to be added here */
  1197. #ifdef DEBUG_PRINT
  1198. DEBUG_PRINT ("Unknown device of type 0x%x n", vol.type);
  1199. #endif
  1200. /* set device back to read array */
  1201. *(UINT32 *) flashPtr = AMD_READ_ARRAY;
  1202. return flUnknownMedia;
  1203. }
  1204.     /* We now have all of the CFI info that we need. Now lets build up 
  1205.      * the sector map and register the erase block sizes. 
  1206.      */
  1207.     if (thisCFI->bootBlockType == BOOTBLOCK_NONE)
  1208. {
  1209. #ifdef DEBUG_PRINT
  1210. DEBUG_PRINT("Debug: Uniform device, no boot blockn");
  1211. #endif
  1212. /* Simplest case is the uniform sector device. Has only one 
  1213.  * sector desc. 
  1214.  */
  1215. for (; thisSector < thisCFI->secDesc[0].numSecs; thisSector++)
  1216.     {
  1217.     thisCFI->secInfo[thisSector].sectorSize = vol.erasableBlockSize;
  1218.     thisCFI->secInfo[thisSector].sectorBaseAdrs = sectorBaseAdrs;
  1219.     sectorBaseAdrs += (CardAddress) vol.erasableBlockSize;
  1220.     }
  1221. }
  1222.     else if (thisCFI->bootBlockType == BOOTBLOCK_BOTTOM)
  1223. {
  1224. #ifdef DEBUG_PRINT
  1225. DEBUG_PRINT("Debug: Bottom boot block devicen");
  1226. #endif
  1227. /* This is a hack but when looking at the data sheets for all of
  1228.  * these devices what comes across is that the CFI data always 
  1229.  * describes a botom boot device. There for we read the sector 
  1230.  * info in the exact order that it is provided in.
  1231.  */
  1232.      for ( ix = 0; ix < thisCFI->sectorDefs; ix++)
  1233.     {
  1234.     int iy;
  1235.             for (iy = 0; iy < thisCFI->secDesc[ix].numSecs; iy++, thisSector++)
  1236.                 {
  1237.      if (thisCFI->secDesc[ix].secSize != 0x00)
  1238.             thisCFI->secInfo[thisSector].sectorSize = 
  1239.     thisCFI->secDesc[ix].secSize * 0x100L;
  1240.      else
  1241.             thisCFI->secInfo[thisSector].sectorSize = 0x80L;
  1242. /* count boot blocks */
  1243. if (thisCFI->secInfo[thisSector].sectorSize != vol.erasableBlockSize)
  1244.     thisCFI->bootBlockSectors++;
  1245.      thisCFI->secInfo[thisSector].sectorBaseAdrs = sectorBaseAdrs;
  1246.      sectorBaseAdrs += (CardAddress) thisCFI->secInfo[thisSector].sectorSize;
  1247.      }
  1248.     }
  1249. }
  1250.     else /* Top boot device */
  1251. {
  1252. int secCount;
  1253. #ifdef DEBUG_PRINT
  1254. DEBUG_PRINT("Debug: Top boot block devicen");
  1255. #endif
  1256. /* First load the descriptions of the uniform sectors and 
  1257.  * then add the sub divisions 
  1258.  */
  1259.      for ( ix = 0; ix < thisCFI->sectorDefs; ix++)
  1260.     {
  1261.     int iy;
  1262.     /* We assume that the unform sectors will never be of the 
  1263.      * variety 128 bytes 
  1264.      */
  1265.     if (vol.erasableBlockSize == thisCFI->secDesc[ix].secSize * 0x100L * vol.interleaving)
  1266. {
  1267.              for (iy = 0; iy < thisCFI->secDesc[ix].numSecs; 
  1268. iy++, thisSector++)
  1269.                     {
  1270.     thisCFI->secInfo[thisSector].sectorSize = 
  1271. vol.erasableBlockSize;
  1272.     thisCFI->secInfo[thisSector].sectorBaseAdrs = 
  1273. sectorBaseAdrs;
  1274.          sectorBaseAdrs += (CardAddress) 
  1275.      thisCFI->secInfo[thisSector].sectorSize;
  1276.     }
  1277. break;
  1278.      }
  1279.     }
  1280. for ( ix = 0, secCount = 0; 
  1281. thisCFI->secDesc[ix].secSize * 0x100L * vol.interleaving
  1282.  != vol.erasableBlockSize; 
  1283. ix++)
  1284.     {
  1285.     int iy;
  1286.     for (iy = 0; iy < thisCFI->secDesc[ix].numSecs; iy++, secCount++)
  1287. {
  1288.      thisCFI->secInfo[(thisCFI->sectorsInCFI - 1) - secCount].sectorSize = 
  1289. thisCFI->secDesc[ix].secSize * 0x100L * vol.interleaving;
  1290. }
  1291.     }
  1292. for (; thisSector <= (thisCFI->sectorsInCFI -1); thisSector++)
  1293.     {
  1294.     thisCFI->secInfo[thisSector].sectorBaseAdrs = sectorBaseAdrs;
  1295.          sectorBaseAdrs += (CardAddress) thisCFI->secInfo[thisSector].sectorSize;
  1296.     thisCFI->bootBlockSectors++;
  1297.     }
  1298. }
  1299. #ifdef DEBUG_PRINT
  1300.     DEBUG_PRINT("Debug: Number of boot block sectors is %dn", thisCFI->bootBlockSectors);
  1301. #endif
  1302.     /* Make sure this comes at the end since the device is set to READ_ARRAY
  1303.      * mode prior to the return
  1304.      */
  1305.     if (cfiAmdChipCountGet(&vol) != flOK)
  1306. return flUnknownMedia;
  1307. #ifdef DEBUG_PRINT
  1308.     DEBUG_PRINT ("Debug: No of chips detected is %dn", vol.noOfChips);
  1309. #if 0
  1310.     for (ix = 0; ix < thisCFI->sectorsInCFI; ix++)
  1311. DEBUG_PRINT ("%2d:0x%x ---  0x%lxn", ix,
  1312. thisCFI->secInfo[ix].sectorBaseAdrs, 
  1313. thisCFI->secInfo[ix].sectorSize);
  1314. #endif
  1315. #endif
  1316.     vol.erase = cfiAmdErase;
  1317.     vol.write = cfiAmdWrite;
  1318.     /* Might have to do this on a bus width basis but for now it seems to
  1319.      * work with Intel devices.
  1320.      */
  1321.     flashPtr[0] = AMD_READ_ARRAY;
  1322.     flashPtr[1] = AMD_READ_ARRAY;
  1323.     flashPtr[2] = AMD_READ_ARRAY;
  1324.     flashPtr[3] = AMD_READ_ARRAY;
  1325.     return flOK;
  1326.     }