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

VxWorks

开发平台:

C/C++

  1. /************************************************************************/
  2. /*                                                                      */
  3. /* FAT-FTL Lite Software Development Kit */
  4. /* Copyright (C) M-Systems Ltd. 1995-1996 */
  5. /* */
  6. /************************************************************************/
  7. /*                                                                      */
  8. /*                    16-bit AMD MTD                                    */
  9. /*                                                                      */
  10. /* This MTD is for flash media which is accessible in 16-bit mode only. */
  11. /* The following Flash technologies are supported:                      */
  12. /*                                                                      */
  13. /* - AMD     Am29F080   8-mbit devices                                  */
  14. /* - AMD     Am29LV080  8-mbit devices                                  */
  15. /* - AMD     Am29F016  16-mbit devices                                  */
  16. /* - Fujitsu MBM29F080  8-mbit devices                                  */
  17. /* */
  18. /************************************************************************/
  19. /*
  20.  * $Log:   V:/wamdmtd.c_v  $
  21.  * 
  22.  *    Rev 1.1   07 Oct 1997 14:58:32   ANDRY
  23.  * get rid of generic names, registration routine returns status
  24.  *
  25.  *    Rev 1.0   25 Aug 1997 12:00:00   ANDRY
  26.  * Initial revision.
  27.  */
  28. #include "flflash.h"
  29. #include "backgrnd.h"
  30. /* JEDEC ids for this MTD */
  31. #define Am29F040_FLASH       0x01a4
  32. #define Am29F080_FLASH       0x01d5
  33. #define Am29LV080_FLASH      0x0138
  34. #define Am29LV008_FLASH      0x0137
  35. #define Am29F016_FLASH       0x01ad
  36. #define Am29F016C_FLASH      0x013d
  37. #define Am29LV017_FLASH      0x01c8
  38. #define Fuj29F040_FLASH      0x04a4
  39. #define Fuj29F080_FLASH      0x04d5
  40. #define Fuj29LV080_FLASH     0x0438
  41. #define Fuj29LV008_FLASH     0x0437
  42. #define Fuj29F016_FLASH      0x04ad
  43. #define Fuj29F016C_FLASH     0x043d
  44. #define Fuj29LV017_FLASH     0x04c8
  45. /* commands for AMD flash */
  46. #define SETUP_ERASE          0x8080
  47. #define SETUP_WRITE          0xa0a0
  48. #define READ_ID              0x9090
  49. #define SUSPEND_ERASE        0xb0b0
  50. #define SECTOR_ERASE         0x3030
  51. #define RESUME_ERASE         0x3030
  52. #define READ_ARRAY           0xf0f0
  53. #define INTEL_READ_ARRAY     0xffff
  54. /* AMD unlocking sequence */
  55. #define UNLOCK_1             0xaaaa
  56. #define UNLOCK_2             0x5555
  57. #define UNLOCK_ADDR1         0x5555
  58. #define UNLOCK_ADDR2         0x2aaa
  59. /* AMD flash status bits */
  60. #define D2                   0x04    /* Toggles when erase suspended */
  61. #define D5                   0x20    /* Set when programming timeout */
  62. #define D6                   0x40    /* Toggles when programming     */
  63. #ifdef __cplusplus
  64.   #define wFlashPtr    ((FlashWPTR &) flashPtr)
  65.   #define wBuffer      ((const unsigned short FAR1 * &) buffer)
  66.   #define wUnlockAddr1 ((FlashWPTR &) unlockAddr1)
  67.   #define wUnlockAddr2 ((FlashWPTR &) unlockAddr2)
  68. #else
  69.   #define wFlashPtr    ((FlashWPTR) flashPtr)
  70.   #define wBuffer      ((const unsigned short FAR1 *) buffer)
  71.   #define wUnlockAddr1 ((FlashWPTR) unlockAddr1)
  72.   #define wUnlockAddr2 ((FlashWPTR) unlockAddr2)
  73. #endif
  74. /* -------------------------------------------------------------------- */
  75. /* AMD Flash specific data. Pointed by FLFlash.mtdVars                  */
  76. /* -------------------------------------------------------------------- */
  77. typedef struct
  78.         {
  79.           FlashWPTR  unlockAddr1;
  80.           FlashWPTR  unlockAddr2;
  81.         } Vars;
  82. static Vars  mtdVars[DRIVES];
  83. #define thisVars   ((Vars *) vol.mtdVars)
  84. /* -------------------------------------------------------------------- */
  85. /*               f l U p d a t e U n l o c k A d d r s                  */
  86. /* */
  87. /* Updates unlock addresses for AMD flash media.                        */
  88. /* */
  89. /* */
  90. /* Parameters:                                                          */
  91. /* vol : Pointer identifying drive */
  92. /*      basePtr         : flash pointer, could point anywhere in the    */
  93. /*                        memory window                                 */
  94. /* */
  95. /* -------------------------------------------------------------------- */
  96. static void flUpdateUnlockAddrs (FLFlash    vol,
  97.                                  FlashWPTR  basePtr)
  98. {
  99.   if ((vol.type == Am29F016C_FLASH) || (vol.type == Fuj29F016C_FLASH))
  100.     thisVars->unlockAddr1 = thisVars->unlockAddr2 = basePtr;
  101.   else
  102.   {
  103.     thisVars->unlockAddr1 = (FlashWPTR)(((long)basePtr & -0x10000l)) + 0x555;
  104.     thisVars->unlockAddr2 = (FlashWPTR)(((long)basePtr & -0x10000l)) + 0x2aa;
  105.   }
  106. }
  107. /*----------------------------------------------------------------------*/
  108. /*                   f l w A m d C o m m a n d                          */
  109. /* */
  110. /* Writes an AMD command with the required unlock sequence */
  111. /* */
  112. /* Parameters:                                                          */
  113. /* vol : Pointer identifying drive */
  114. /*      address : Card address at which to write command */
  115. /* command : command to write */
  116. /*                                                                      */
  117. /*----------------------------------------------------------------------*/
  118. static void flwAmdCommand (FLFlash         vol,
  119.                            CardAddress     address,
  120.                            unsigned short  command)
  121. {
  122.   if (thisVars->unlockAddr1)
  123.   {
  124.     thisVars->unlockAddr1[0] = UNLOCK_1;
  125.     thisVars->unlockAddr2[0] = UNLOCK_2;
  126.     thisVars->unlockAddr1[0] = command;
  127.   }
  128.   else
  129.   {
  130.     CardAddress  baseAddress  = address & (-0x10000l);
  131.     /* write AMD unlock sequence */
  132.     *(FlashWPTR) vol.map (&vol,
  133.                           baseAddress + 2 * UNLOCK_ADDR1,
  134.                           vol.interleaving) = UNLOCK_1;
  135.     *(FlashWPTR) vol.map (&vol,
  136.                           baseAddress + 2 * UNLOCK_ADDR2,
  137.                           vol.interleaving) = UNLOCK_2;
  138.     /* write flash command */
  139.     *(FlashWPTR) vol.map (&vol,
  140.                           baseAddress + 2 * UNLOCK_ADDR1,
  141.                           vol.interleaving) = command;
  142.     vol.map (&vol, address, vol.interleaving);
  143.   }
  144. }
  145. /*----------------------------------------------------------------------*/
  146. /*                f l w A m d M T D W r i t e                           */
  147. /* */
  148. /* Write a block of bytes to Flash */
  149. /* */
  150. /* This routine will be registered as FLFlash.write routine             */
  151. /* */
  152. /* Parameters:                                                          */
  153. /* vol : Pointer identifying drive */
  154. /*      address : Card address to write to */
  155. /*      buffer : Address of data to write */
  156. /* length : Number of bytes to write */
  157. /* overwrite : TRUE if overwriting old Flash contents */
  158. /*   FALSE if old contents are known to be erased */
  159. /*                                                                      */
  160. /* Returns:                                                             */
  161. /*      FLStatus        : 0 on success, failed otherwise                */
  162. /*----------------------------------------------------------------------*/
  163. static FLStatus flwAmdMTDWrite (FLFlash           vol,
  164.                                 CardAddress       address,
  165.                                 const void FAR1  *buffer,
  166.                                 int               length,
  167.                                 FLBoolean         overwrite)
  168. {
  169.   unsigned long writeTimeout;
  170.   int           cLength;
  171.   FlashWPTR     flashPtr,
  172.                 unlockAddr1 = thisVars->unlockAddr1,
  173.                 unlockAddr2 = thisVars->unlockAddr2;
  174.   if ( flWriteProtected(vol.socket) )
  175.     return flWriteProtect;
  176.   flashPtr = (FlashWPTR) vol.map (&vol, address, length);
  177.   /* set addresses for AMD unlock sequence */
  178.   flUpdateUnlockAddrs (&vol, flashPtr);
  179.   unlockAddr1 = thisVars->unlockAddr1;
  180.   unlockAddr2 = thisVars->unlockAddr2;
  181.   /* Set timeout to 5 seconds from now */
  182.   writeTimeout = flMsecCounter + 5000;
  183.   /* write the data */
  184.   cLength = length;
  185.   while (cLength >= 2)
  186.   {
  187.     /* AMD unlock sequence */
  188.     *wUnlockAddr1 = UNLOCK_1;
  189.     *wUnlockAddr2 = UNLOCK_2;
  190.     /* flash command */
  191.     *wUnlockAddr1 = SETUP_WRITE;
  192.     /* write user data word */
  193.     *wFlashPtr    = *wBuffer;
  194.     /* wait for ready */
  195.     while ((*wFlashPtr != *wBuffer)    && (flMsecCounter < writeTimeout))
  196.     {
  197.       if( ((*wFlashPtr &          D5)  && ((*wFlashPtr ^ *wBuffer) &   0xff))
  198.                  ||
  199.           ((*wFlashPtr & (0x100 * D5)) && ((*wFlashPtr ^ *wBuffer) & 0xff00)) )
  200.       {
  201.         *wFlashPtr = READ_ARRAY;
  202.         return flWriteFault;
  203.       }
  204.     }
  205.     cLength -= 2;
  206.     /* replaced wBuffer++; wFlashPtr++; */
  207.     buffer = (unsigned char *)buffer + sizeof(unsigned short);
  208.     flashPtr = (FlashWPTR)flashPtr + 1;
  209.   }
  210.   /* verify the written data */
  211.   /* replaced: wFlashPtr -= length/2; wBuffer -= length/2; */
  212.   flashPtr -= length / 2;
  213.   buffer = (unsigned short *)buffer - (length/2);
  214.   if (tffscmp((void FAR0 *)flashPtr, buffer, length))
  215.     return flWriteFault;
  216.   return flOK;
  217. }
  218. /*----------------------------------------------------------------------*/
  219. /*               f l w A m d M T D E r a s e                            */
  220. /* */
  221. /* Erase one or more contiguous Flash erasable blocks */
  222. /* */
  223. /* This routine will be registered as FLFlash.erase routine             */
  224. /* */
  225. /* Parameters:                                                          */
  226. /*      vol                : Pointer identifying drive                  */
  227. /*      firstBlock         : Number of first block to erase             */
  228. /*      numOfBlocks        : Number of blocks to erase                  */
  229. /*                                                                      */
  230. /* Returns:                                                             */
  231. /*      FLStatus           : 0 on success, failed otherwise             */
  232. /*----------------------------------------------------------------------*/
  233. static FLStatus flwAmdMTDErase (FLFlash  vol,
  234.                                 int      firstBlock,
  235.                                 int      numOfBlocks)
  236. {
  237.   FlashWPTR  flashPtr;
  238.   FLBoolean  finished;
  239.   int        iBlock;
  240.   if ( flWriteProtected(vol.socket) )
  241.     return flWriteProtect;
  242.   for (iBlock = 0;  iBlock < numOfBlocks;  iBlock++)
  243.   {
  244.     flashPtr = (FlashWPTR) vol.map( &vol,
  245.                                    (firstBlock + iBlock) * vol.erasableBlockSize,
  246.                                     vol.interleaving);
  247.     flUpdateUnlockAddrs (&vol, flashPtr);
  248.     flwAmdCommand (&vol, 0, SETUP_ERASE);
  249.     flwAmdCommand (&vol, 0, SECTOR_ERASE);
  250.     do {
  251. #ifdef BACKGROUND
  252.       while (flForeground(1) == BG_SUSPEND) { /* suspend */
  253.         for (i = 0; i < interleave; i++) {
  254.   flashPtr[i] = SUSPEND_ERASE;
  255.   /* Wait for D6 to stop toggling */
  256.   while ((flashPtr[i] ^ flashPtr[i]) & D6)
  257.     ;
  258. }
  259.       } /* while (foreground..) */
  260. #endif
  261.       finished = TRUE;
  262.       if (*wFlashPtr != 0xffff)
  263.       {
  264.         if( ((*wFlashPtr &   0xff &          D5)  && ((*wFlashPtr &   0xff) !=   0xff))
  265.                 ||
  266.             ((*wFlashPtr & 0xff00 & (0x100 * D5)) && ((*wFlashPtr & 0xff00) != 0xff00)) )
  267.         {
  268.           *wFlashPtr = READ_ARRAY;
  269.           return flWriteFault;
  270.         }
  271.         finished = FALSE;
  272.       }
  273.     } while (!finished);
  274.   }
  275.   return flOK;
  276. }
  277. /*----------------------------------------------------------------------*/
  278. /*                     f l w A m d I d e n t i f y                      */
  279. /* */
  280. /* Identify the AMD Flash media.                                        */
  281. /* Sets the value of flash.type (JEDEC id) & FLFlash.interleaving. */
  282. /* */
  283. /* Parameters:                                                          */
  284. /*      vol             : Pointer identifying drive                     */
  285. /* amdCmdRoutine : Routine to read-id AMD/Fujitsu style at */
  286. /*   a specific location. If null, Intel procedure */
  287. /*   is used.                                      */
  288. /*      idOffset : Chip offset to use for identification */
  289. /*                                                                      */
  290. /*----------------------------------------------------------------------*/
  291. void flwAmdIdentify (FLFlash      vol,
  292.                             void (*amdCmdRoutine)(FLFlash vol, CardAddress, unsigned short),
  293.                             CardAddress  idOffset)
  294. {
  295.   unsigned short  resetCmd  = amdCmdRoutine ? READ_ARRAY : INTEL_READ_ARRAY;
  296.   FlashWPTR       flashPtr  = (FlashWPTR) flMap (vol.socket, idOffset);
  297.   vol.noOfChips = 0;
  298.   flashPtr[0] = resetCmd;          /* Reset chips             */
  299.   flashPtr[0] = resetCmd;          /* Once again for luck     */
  300.   if (amdCmdRoutine)               /* use AMD unlock sequence */
  301.   {
  302.     flUpdateUnlockAddrs (&vol, flashPtr);
  303.     amdCmdRoutine (&vol, idOffset, READ_ID);
  304.   }
  305.   else
  306.     flashPtr[0] = READ_ID;         /* use Intel-style         */
  307.   vol.type = (FlashType) ((flashPtr[0] & 0xff00) | (flashPtr[1] & 0xff));
  308.   flashPtr[0] = resetCmd;
  309. }
  310. /*----------------------------------------------------------------------*/
  311. /*                       f l w A m d S i z e                            */
  312. /* */
  313. /* Identify the card size for AMD Flash.                                */
  314. /* Sets the value of flash.noOfChips. */
  315. /* */
  316. /* Parameters:                                                          */
  317. /* vol : Pointer identifying drive */
  318. /* amdCmdRoutine : Routine to read-id AMD/Fujitsu style at */
  319. /*   a specific location. If null, Intel procedure */
  320. /*   is used.                                      */
  321. /*      idOffset : Chip offset to use for identification */
  322. /*                                                                      */
  323. /* Returns:                                                             */
  324. /*      FLStatus        : 0 = OK, otherwise failed (invalid Flash array)*/
  325. /*----------------------------------------------------------------------*/
  326. FLStatus flwAmdSize (FLFlash      vol,
  327.                    void (*amdCmdRoutine)(FLFlash vol, CardAddress, unsigned short),
  328.                    CardAddress  idOffset)
  329. {
  330.   unsigned short  resetCmd = amdCmdRoutine ? READ_ARRAY : INTEL_READ_ARRAY;
  331.   FlashWPTR       flashPtr = (FlashWPTR) vol.map (&vol, idOffset, 0);
  332.   if (amdCmdRoutine)             /* use AMD unlock sequence      */
  333.   {
  334.     flUpdateUnlockAddrs(&vol, flashPtr);
  335.     amdCmdRoutine (&vol, idOffset, READ_ID);
  336.   }
  337.   else
  338.     flashPtr[0] = READ_ID;       /* use Intel-style              */
  339.   /* We left the first chip in Read ID mode, so that we can      */
  340.   /* discover an address wraparound.                             */
  341.   for (vol.noOfChips = 1;  vol.noOfChips < 2000;  vol.noOfChips++)
  342.   {
  343.     flashPtr = (FlashWPTR)
  344.                 vol.map (&vol, vol.noOfChips * vol.chipSize + idOffset, 0);
  345.     /* Read ID from the chips without issuing a READ_ID command. */
  346.     /* Check for address wraparound to the first chip.           */
  347.     if ((FlashType)((flashPtr[0] & 0xff00) | (flashPtr[1] & 0xff)) == vol.type)
  348.       break;                     /* wraparound to the first chip */
  349.     /* Check if chip displays the same JEDEC id and interleaving */
  350.     if (amdCmdRoutine)           /* AMD: use unlock sequence     */
  351.     {
  352.       flUpdateUnlockAddrs (&vol, flashPtr);
  353.       amdCmdRoutine (&vol,
  354.                      vol.noOfChips * vol.chipSize + idOffset,
  355.                      READ_ID);
  356.     }
  357.     else
  358.       flashPtr[0] = READ_ID;     /* use Intel-style              */
  359.     if ((FlashType) ((flashPtr[0] & 0xff00) | (flashPtr[1] & 0xff)) != vol.type)
  360.     {
  361.       /* This "chip" doesn't respond correctly, so we're done */
  362.       break;
  363.     }
  364.     flashPtr[0] = resetCmd;
  365.   }
  366.   flashPtr = (FlashWPTR) vol.map (&vol, idOffset, 0);
  367.   flashPtr[0] = resetCmd;        /* reset the original chip      */
  368.   return (vol.noOfChips == 0) ? flUnknownMedia : flOK;
  369. }
  370. /*----------------------------------------------------------------------*/
  371. /*              f l w A m d M T D I d e n t i f y                       */
  372. /* */
  373. /* Identifies AMD flash media accessible in 16-bit mode only.           */
  374. /* */
  375. /* This routine will be placed on the MTD list in CUSTOM.C. It must be  */
  376. /* an extern routine. */
  377. /* */
  378. /* On successful identification, the Flash structure is filled out and */
  379. /* the write and erase routines registered. */
  380. /* */
  381. /* Parameters:                                                          */
  382. /* vol : Pointer identifying drive */
  383. /*                                                                      */
  384. /* Returns:                                                             */
  385. /*      FLStatus        : 0 = OK, otherwise failed (invalid Flash array)*/
  386. /*----------------------------------------------------------------------*/
  387. FLStatus flwAmdMTDIdentify (FLFlash vol)
  388. {
  389.   FlashWPTR  baseFlashPtr;
  390.   flSetWindowBusWidth (vol.socket,16);      /* use 16-bits */
  391.   flSetWindowSpeed (vol.socket,120);        /* 120 nsec.   */
  392.   /* place to store all the AMD-specific flash parametes */
  393.   vol.mtdVars = &mtdVars[flSocketNoOf(vol.socket)];
  394.   thisVars->unlockAddr1 = NULL;
  395.   vol.interleaving = 2;
  396.   flwAmdIdentify (&vol, flwAmdCommand, 0);
  397.   if (vol.type == Am29F016_FLASH   || vol.type == Fuj29F016_FLASH  ||
  398.       vol.type == Am29F016C_FLASH  || vol.type == Fuj29F016C_FLASH ||
  399.       vol.type == Am29LV017_FLASH  || vol.type == Fuj29LV017_FLASH)
  400.     vol.chipSize = 0x200000l * vol.interleaving;
  401.   else
  402.   if (vol.type == Fuj29F080_FLASH  || vol.type == Am29F080_FLASH   ||
  403.       vol.type == Fuj29LV080_FLASH || vol.type == Am29LV080_FLASH  ||
  404.       vol.type == Fuj29LV008_FLASH || vol.type == Am29LV008_FLASH)
  405.     vol.chipSize = 0x100000l * vol.interleaving;
  406.   else
  407.   if (vol.type == Fuj29F040_FLASH  ||  vol.type == Am29F040_FLASH)
  408.     vol.chipSize = 0x80000l * vol.interleaving;
  409.   else
  410.     return flUnknownMedia;
  411.   /* find where the window is */
  412.   baseFlashPtr = (FlashWPTR)
  413.                   vol.map (&vol, (CardAddress)0, vol.interleaving);
  414.   flUpdateUnlockAddrs (&vol, baseFlashPtr);
  415.   checkStatus( flwAmdSize(&vol, flwAmdCommand, 0) );
  416.   vol.erasableBlockSize = 0x10000l * vol.interleaving;
  417.   vol.flags            |= SUSPEND_FOR_WRITE;
  418.   /* Register our flash handlers */
  419.   vol.write = flwAmdMTDWrite;
  420.   vol.erase = flwAmdMTDErase;
  421.   return flOK;
  422. }
  423. #if FALSE
  424. /*----------------------------------------------------------------------*/
  425. /*                 f l R e g i s t e r W A M D M T D                    */
  426. /* */
  427. /* Registers this MTD for use */
  428. /* */
  429. /* Parameters:                                                          */
  430. /* None */
  431. /*                                                                      */
  432. /*----------------------------------------------------------------------*/
  433. FLStatus  flRegisterWAMDMTD (void)
  434. {
  435.   if (noOfMTDs >= MTDS)
  436.     return flTooManyComponents;
  437.   mtdTable[noOfMTDs++] = flwAmdMTDIdentify;
  438.   return flOK;
  439. }
  440. #endif /* FALSE */