Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

747 lines
22 KiB

  1. /*
  2. * $Log: P:/user/amir/lite/vcs/amdmtd.c_v $
  3. *
  4. * Rev 1.21 03 Nov 1997 16:07:06 danig
  5. * Support RFA
  6. *
  7. * Rev 1.20 02 Nov 1997 11:06:38 ANDRY
  8. * bug fix in AMDErase() for RFA on PowerPC
  9. *
  10. * Rev 1.19 20 Oct 1997 14:08:56 danig
  11. * Resume erase only when needed
  12. *
  13. * Rev 1.18 19 Oct 1997 16:39:50 danig
  14. * Deal with the last word in interleaving 4
  15. *
  16. * Rev 1.17 29 Sep 1997 18:21:08 danig
  17. * Try different interleavings in amdMTDIdentify()
  18. *
  19. * Rev 1.16 24 Sep 1997 17:45:52 danig
  20. * Default interleaving value is 4
  21. *
  22. * Rev 1.15 10 Sep 1997 16:22:00 danig
  23. * Got rid of generic names
  24. *
  25. * Rev 1.14 08 Sep 1997 18:56:50 danig
  26. * Support interleaving 4
  27. *
  28. * Rev 1.13 04 Sep 1997 17:39:34 danig
  29. * Debug messages
  30. *
  31. * Rev 1.12 31 Aug 1997 14:53:48 danig
  32. * Registration routine return status
  33. *
  34. * Rev 1.11 10 Aug 1997 17:56:02 danig
  35. * Comments
  36. *
  37. * Rev 1.10 24 Jul 1997 17:51:54 amirban
  38. * FAR to FAR0
  39. *
  40. * Rev 1.9 20 Jul 1997 17:16:54 amirban
  41. * No watchDogTimer
  42. *
  43. * Rev 1.8 07 Jul 1997 15:20:54 amirban
  44. * Ver 2.0
  45. *
  46. * Rev 1.5 06 Feb 1997 18:18:34 danig
  47. * Different unlock addresses for series C
  48. *
  49. * Rev 1.4 17 Nov 1996 15:45:16 danig
  50. * added LV017 support.
  51. *
  52. * Rev 1.3 14 Oct 1996 17:57:00 danig
  53. * new IDs and eraseFirstBlockLV008.
  54. *
  55. * Rev 1.2 09 Sep 1996 11:38:26 amirban
  56. * Correction for Fujitsu 8-mbit
  57. *
  58. * Rev 1.1 29 Aug 1996 14:14:46 amirban
  59. * Warnings
  60. *
  61. * Rev 1.0 15 Aug 1996 15:16:38 amirban
  62. * Initial revision.
  63. */
  64. /************************************************************************/
  65. /* */
  66. /* FAT-FTL Lite Software Development Kit */
  67. /* Copyright (C) M-Systems Ltd. 1995-1996 */
  68. /* */
  69. /************************************************************************/
  70. /*----------------------------------------------------------------------*/
  71. /* */
  72. /* This MTD supports the following Flash technologies: */
  73. /* */
  74. /* - AMD Am29F080 8-mbit devices */
  75. /* - AMD Am29LV080 8-mbit devices */
  76. /* - AMD Am29F016 16-mbit devices */
  77. /* - Fujitsu MBM29F080 8-mbit devices */
  78. /* */
  79. /* And (among others) the following Flash media and cards: */
  80. /* */
  81. /* - AMD Series-D PCMCIA cards */
  82. /* - AMD AmMC0XXA Miniature cards */
  83. /* - AMD AmMCL0XXA Miniature cards */
  84. /* */
  85. /*----------------------------------------------------------------------*/
  86. #include "flflash.h"
  87. #ifdef FL_BACKGROUND
  88. #include "backgrnd.h"
  89. #endif
  90. #define NO_UNLOCK_ADDR 0xffffffffL
  91. typedef struct {
  92. ULONG unlockAddr1,
  93. unlockAddr2;
  94. ULONG baseMask;
  95. } Vars;
  96. Vars mtdVars_amdmtd[SOCKETS];
  97. #define thisVars ((Vars *) vol.mtdVars)
  98. #define SETUP_ERASE 0x80
  99. #define SETUP_WRITE 0xa0
  100. #define READ_ID 0x90
  101. #define SUSPEND_ERASE 0xb0
  102. #define SECTOR_ERASE 0x30
  103. #define RESUME_ERASE 0x30
  104. #define READ_ARRAY 0xf0
  105. #define UNLOCK_1 0xaa
  106. #define UNLOCK_2 0x55
  107. #define UNLOCK_ADDR1 0x5555u
  108. #define UNLOCK_ADDR2 0x2aaau
  109. #define D2 4 /* Toggles when erase suspended */
  110. #define D5 0x20 /* Set when programming timeout */
  111. #define D6 0x40 /* Toggles when programming */
  112. /* JEDEC ids for this MTD */
  113. #define Am29F040_FLASH 0x01a4
  114. #define Am29F080_FLASH 0x01d5
  115. #define Am29LV080_FLASH 0x0138
  116. #define Am29LV008_FLASH 0x0137
  117. #define Am29F016_FLASH 0x01ad
  118. #define Am29F016C_FLASH 0x013d
  119. #define Am29LV017_FLASH 0x01c8
  120. #define Fuj29F040_FLASH 0x04a4
  121. #define Fuj29F080_FLASH 0x04d5
  122. #define Fuj29LV080_FLASH 0x0438
  123. #define Fuj29LV008_FLASH 0x0437
  124. #define Fuj29F016_FLASH 0x04ad
  125. #define Fuj29F016C_FLASH 0x043d
  126. #define Fuj29LV017_FLASH 0x04c8
  127. /*----------------------------------------------------------------------*/
  128. /* m a p B a s e */
  129. /* */
  130. /* Map the window to a page base (page is 4KB or 32KB depends on the */
  131. /* media type) and return a pointer to the base. Also return the offset */
  132. /* of the given address from the base. */
  133. /* */
  134. /* Parameters: */
  135. /* vol : Pointer identifying drive */
  136. /* address : Card address to map */
  137. /* offset : receives the offset from the base */
  138. /* length : length to map */
  139. /* */
  140. /* Returns: */
  141. /* FlashPTR : pointer to the page base. */
  142. /* */
  143. /*----------------------------------------------------------------------*/
  144. FlashPTR mapBase(FLFlash vol,
  145. CardAddress address,
  146. ULONG *offset,
  147. LONG length)
  148. {
  149. CardAddress base = address & thisVars->baseMask;
  150. *offset = (ULONG)(address - base);
  151. return (FlashPTR)flMap(vol.socket, base);
  152. }
  153. /*----------------------------------------------------------------------*/
  154. /* a m d C o m m a n d */
  155. /* */
  156. /* Writes an AMD command with the required unlock sequence */
  157. /* */
  158. /* Parameters: */
  159. /* vol : Pointer identifying drive */
  160. /* address : Card address at which to write command */
  161. /* command : command to write */
  162. /* flashPtr : pointer to the window */
  163. /* */
  164. /*----------------------------------------------------------------------*/
  165. VOID amdCommand(FLFlash vol,
  166. CardAddress address,
  167. UCHAR command,
  168. FlashPTR flashPtr)
  169. {
  170. if (thisVars->unlockAddr1 != NO_UNLOCK_ADDR) {
  171. tffsWriteByteFlash(flAddLongToFarPointer((VOID FAR0 *)flashPtr,
  172. ((LONG) address & (vol.interleaving - 1)) + thisVars->unlockAddr1)
  173. ,UNLOCK_1);
  174. tffsWriteByteFlash(flAddLongToFarPointer((VOID FAR0 *)flashPtr,
  175. ((LONG) address & (vol.interleaving - 1)) + thisVars->unlockAddr2)
  176. ,UNLOCK_2);
  177. tffsWriteByteFlash(flAddLongToFarPointer((VOID FAR0 *)flashPtr,
  178. ((LONG) address & (vol.interleaving - 1)) + thisVars->unlockAddr1)
  179. ,command);
  180. }
  181. else {
  182. CardAddress baseAddress = address & (-0x10000l | (vol.interleaving - 1));
  183. tffsWriteByteFlash(flMap(vol.socket,baseAddress + vol.interleaving * UNLOCK_ADDR1),
  184. UNLOCK_1);
  185. tffsWriteByteFlash(flMap(vol.socket,baseAddress + vol.interleaving * UNLOCK_ADDR2),
  186. UNLOCK_2);
  187. tffsWriteByteFlash(flMap(vol.socket,baseAddress + vol.interleaving * UNLOCK_ADDR1),
  188. command);
  189. flMap(vol.socket, address);
  190. }
  191. }
  192. /*----------------------------------------------------------------------*/
  193. /* a m d M T D W r i t e */
  194. /* */
  195. /* Write a block of bytes to Flash */
  196. /* */
  197. /* This routine will be registered as the MTD vol.write routine */
  198. /* */
  199. /* Parameters: */
  200. /* vol : Pointer identifying drive */
  201. /* address : Card address to write to */
  202. /* buffer : Address of data to write */
  203. /* length : Number of bytes to write */
  204. /* overwrite : TRUE if overwriting old Flash contents */
  205. /* FALSE if old contents are known to be erased */
  206. /* */
  207. /* Returns: */
  208. /* FLStatus : 0 on success, failed otherwise */
  209. /*----------------------------------------------------------------------*/
  210. FLStatus amdMTDWrite(FLFlash vol,
  211. CardAddress address,
  212. const VOID FAR1 *buffer,
  213. dword length,
  214. word overwrite)
  215. {
  216. /* Set timeout to 5 seconds from now */
  217. ULONG writeTimeout = flMsecCounter + 5000;
  218. LONG cLength, i;
  219. FlashPTR flashPtr, unlockAddr1, unlockAddr2;
  220. ULONG offset;
  221. if (flWriteProtected(vol.socket))
  222. return flWriteProtect;
  223. flashPtr = mapBase(&vol, address, &offset, length);
  224. unlockAddr1 = (FlashPTR) flAddLongToFarPointer((VOID FAR0 *)flashPtr,
  225. thisVars->unlockAddr1);
  226. unlockAddr2 = (FlashPTR) flAddLongToFarPointer((VOID FAR0 *)flashPtr,
  227. thisVars->unlockAddr2);
  228. flashPtr = (FlashPTR) flAddLongToFarPointer((VOID FAR0 *)flashPtr,
  229. offset);
  230. cLength = length;
  231. if (vol.interleaving == 1) {
  232. lastByte:
  233. #ifdef __cplusplus
  234. #define bFlashPtr flashPtr
  235. #define bBuffer ((const UCHAR FAR1 * &) buffer)
  236. #else
  237. #define bFlashPtr flashPtr
  238. #define bBuffer ((const UCHAR FAR1 *) buffer)
  239. #endif
  240. while (cLength >= 1) {
  241. tffsWriteByteFlash(unlockAddr1, UNLOCK_1);
  242. tffsWriteByteFlash(unlockAddr2, UNLOCK_2);
  243. tffsWriteByteFlash(unlockAddr1,SETUP_WRITE);
  244. tffsWriteByteFlash(bFlashPtr, *bBuffer);
  245. cLength--;
  246. bBuffer++;
  247. bFlashPtr++;
  248. while (tffsReadByteFlash(bFlashPtr-1) != bBuffer[-1] && flMsecCounter < writeTimeout) {
  249. if ((tffsReadByteFlash(bFlashPtr-1) & D5) &&
  250. tffsReadByteFlash(bFlashPtr-1) != bBuffer[-1]) {
  251. tffsWriteByteFlash(bFlashPtr-1, READ_ARRAY);
  252. DEBUG_PRINT(("Debug: write failed in AMD MTD.\n"));
  253. return flWriteFault;
  254. }
  255. }
  256. }
  257. }
  258. else if (vol.interleaving == 2) {
  259. lastWord:
  260. #ifdef __cplusplus
  261. #define wFlashPtr ((FlashWPTR &) flashPtr)
  262. #define wBuffer ((const USHORT FAR1 * &) buffer)
  263. #define wUnlockAddr1 ((FlashWPTR &) unlockAddr1)
  264. #define wUnlockAddr2 ((FlashWPTR &) unlockAddr2)
  265. #else
  266. #define wFlashPtr ((FlashWPTR) flashPtr)
  267. #define wBuffer ((const USHORT FAR1 *) buffer)
  268. #define wUnlockAddr1 ((FlashWPTR) unlockAddr1)
  269. #define wUnlockAddr2 ((FlashWPTR) unlockAddr2)
  270. #endif
  271. while (cLength >= 2) {
  272. tffsWriteWordFlash(wUnlockAddr1, UNLOCK_1 * 0x101);
  273. tffsWriteWordFlash(wUnlockAddr2, UNLOCK_2 * 0x101);
  274. tffsWriteWordFlash(wUnlockAddr1, SETUP_WRITE * 0x101);
  275. tffsWriteWordFlash(wFlashPtr, *wBuffer);
  276. cLength -= 2;
  277. wBuffer++;
  278. wFlashPtr++;
  279. while ((tffsReadWordFlash(wFlashPtr-1) != wBuffer[-1]) && (flMsecCounter < writeTimeout)) {
  280. if (((tffsReadWordFlash(wFlashPtr-1) & D5) &&
  281. ((tffsReadWordFlash(wFlashPtr-1) ^ wBuffer[-1]) & 0xff))
  282. ||
  283. ((tffsReadWordFlash(wFlashPtr-1) & (D5 * 0x100)) &&
  284. ((tffsReadWordFlash(wFlashPtr-1) ^ wBuffer[-1]) & 0xff00))) {
  285. tffsWriteWordFlash(wFlashPtr-1, READ_ARRAY * 0x101);
  286. DEBUG_PRINT(("Debug: write failed in AMD MTD.\n"));
  287. return flWriteFault;
  288. }
  289. }
  290. }
  291. if (cLength > 0)
  292. goto lastByte;
  293. }
  294. else /* if (vol.interleaving >= 4) */ {
  295. #ifdef __cplusplus
  296. #define dFlashPtr ((FlashDPTR &) flashPtr)
  297. #define dBuffer ((const ULONG FAR1 * &) buffer)
  298. #define dUnlockAddr1 ((FlashDPTR &) unlockAddr1)
  299. #define dUnlockAddr2 ((FlashDPTR &) unlockAddr2)
  300. #else
  301. #define dFlashPtr ((FlashDPTR) flashPtr)
  302. #define dBuffer ((const ULONG FAR1 *) buffer)
  303. #define dUnlockAddr1 ((FlashDPTR) unlockAddr1)
  304. #define dUnlockAddr2 ((FlashDPTR) unlockAddr2)
  305. #endif
  306. while (cLength >= 4) {
  307. tffsWriteDwordFlash(dUnlockAddr1, UNLOCK_1 * 0x1010101lu);
  308. tffsWriteDwordFlash(dUnlockAddr2, UNLOCK_2 * 0x1010101lu);
  309. tffsWriteDwordFlash(dUnlockAddr1, SETUP_WRITE * 0x1010101lu);
  310. tffsWriteDwordFlash(dFlashPtr, *dBuffer);
  311. cLength -= 4;
  312. dBuffer++;
  313. dFlashPtr++;
  314. while ((tffsReadDwordFlash(dFlashPtr-1) != dBuffer[-1]) && (flMsecCounter < writeTimeout)) {
  315. if (((tffsReadDwordFlash(dFlashPtr-1) & D5) &&
  316. ((tffsReadDwordFlash(dFlashPtr-1) ^ dBuffer[-1]) & 0xff))
  317. ||
  318. ((tffsReadDwordFlash(dFlashPtr-1) & (D5 * 0x100)) &&
  319. ((tffsReadDwordFlash(dFlashPtr-1) ^ dBuffer[-1]) & 0xff00))
  320. ||
  321. ((tffsReadDwordFlash(dFlashPtr-1) & (D5 * 0x10000lu)) &&
  322. ((tffsReadDwordFlash(dFlashPtr-1) ^ dBuffer[-1]) & 0xff0000lu))
  323. ||
  324. ((tffsReadDwordFlash(dFlashPtr-1) & (D5 * 0x1000000lu)) &&
  325. ((tffsReadDwordFlash(dFlashPtr-1) ^ dBuffer[-1]) & 0xff000000lu))) {
  326. tffsWriteDwordFlash(dFlashPtr-1, READ_ARRAY * 0x1010101lu);
  327. DEBUG_PRINT(("Debug: write failed in AMD MTD.\n"));
  328. return flWriteFault;
  329. }
  330. }
  331. }
  332. if (cLength > 0)
  333. goto lastWord;
  334. }
  335. flashPtr -= length;
  336. bBuffer -= length;
  337. /* compare double words */
  338. for(;length >= 4; length -= 4, dFlashPtr++, dBuffer++) {
  339. if (tffsReadDwordFlash(dFlashPtr) != *dBuffer) {
  340. DEBUG_PRINT(("Debug: write failed in AMD MTD on verification.\n"));
  341. return flWriteFault;
  342. }
  343. }
  344. /* compare the last bytes */
  345. for(; length; length--, bFlashPtr++, bBuffer++) {
  346. if (tffsReadByteFlash(bFlashPtr) != *bBuffer) {
  347. DEBUG_PRINT(("Debug: write failed in AMD MTD on verification.\n"));
  348. return flWriteFault;
  349. }
  350. }
  351. return flOK;
  352. }
  353. /*----------------------------------------------------------------------*/
  354. /* e r a s e F i r s t B l o c k L V 0 0 8 */
  355. /* */
  356. /* Erase the first block in LV008 chip. This block is devided into four */
  357. /* subblocks 16, 8, 8, and 32 kbytes in size. */
  358. /* */
  359. /* Parameters: */
  360. /* vol : Pointer identifying drive */
  361. /* firstErasableBlock : Number of block to erase */
  362. /* */
  363. /* Returns: */
  364. /* FLStatus : 0 on success, failed otherwise */
  365. /*----------------------------------------------------------------------*/
  366. FLStatus eraseFirstBlockLV008(FLFlash vol, LONG firstErasableBlock)
  367. {
  368. LONG iSubBlock;
  369. LONG subBlockSize = 0;
  370. for (iSubBlock = 0; iSubBlock < 4; iSubBlock++) {
  371. LONG i;
  372. FlashPTR flashPtr;
  373. FLBoolean finished;
  374. switch (iSubBlock) {
  375. case 1:
  376. subBlockSize = 0x4000;
  377. break;
  378. case 2:
  379. case 3:
  380. subBlockSize = 0x2000;
  381. break;
  382. }
  383. flashPtr = (FlashPTR)
  384. flMap(vol.socket,
  385. firstErasableBlock + subBlockSize * vol.interleaving);
  386. for (i = 0; i < vol.interleaving; i++) {
  387. amdCommand(&vol, i,SETUP_ERASE, flashPtr);
  388. tffsWriteByteFlash((FlashPTR) flAddLongToFarPointer((VOID FAR0 *)flashPtr,
  389. i + thisVars->unlockAddr1), UNLOCK_1);
  390. tffsWriteByteFlash((FlashPTR) flAddLongToFarPointer((VOID FAR0 *)flashPtr,
  391. i + thisVars->unlockAddr2), UNLOCK_2);
  392. tffsWriteByteFlash(flashPtr+i, SECTOR_ERASE);
  393. }
  394. do {
  395. #ifdef FL_BACKGROUND
  396. while (flForeground(1) == BG_SUSPEND) { /* suspend */
  397. for (i = 0; i < vol.interleaving; i++) {
  398. tffsWriteByteFlash(flashPtr+i, SUSPEND_ERASE);
  399. /* Wait for D6 to stop toggling */
  400. while ((tffsReadByteFlash(flashPtr+i) ^ tffsReadByteFlash(flashPtr+i))
  401. & D6)
  402. ;
  403. }
  404. }
  405. #endif
  406. finished = TRUE;
  407. for (i = 0; i < vol.interleaving; i++) {
  408. tffsWriteByteFlash(flashPtr+i, RESUME_ERASE);
  409. if (tffsReadByteFlash(flashPtr+i) != 0xff) {
  410. if ((tffsReadByteFlash(flashPtr+i) & D5) &&
  411. tffsReadByteFlash(flashPtr+i) != 0xff) {
  412. tffsWriteByteFlash(flashPtr+i, READ_ARRAY);
  413. return flWriteFault;
  414. }
  415. finished = FALSE;
  416. }
  417. }
  418. } while (!finished);
  419. }
  420. return flOK;
  421. }
  422. /*----------------------------------------------------------------------*/
  423. /* a m d M T D E r a s e */
  424. /* */
  425. /* Erase one or more contiguous Flash erasable blocks */
  426. /* */
  427. /* This routine will be registered as the MTD vol.erase routine */
  428. /* */
  429. /* Parameters: */
  430. /* vol : Pointer identifying drive */
  431. /* firstErasableBlock : Number of first block to erase */
  432. /* numOfErasableBlocks: Number of blocks to erase */
  433. /* */
  434. /* Returns: */
  435. /* FLStatus : 0 on success, failed otherwise */
  436. /*----------------------------------------------------------------------*/
  437. FLStatus amdMTDErase(FLFlash vol,
  438. word firstErasableBlock,
  439. word numOfErasableBlocks)
  440. {
  441. LONG iBlock;
  442. if (flWriteProtected(vol.socket))
  443. return flWriteProtect;
  444. for (iBlock = 0; iBlock < numOfErasableBlocks; iBlock++) {
  445. LONG i;
  446. FLBoolean finished;
  447. FlashPTR flashPtr;
  448. /* The first block in an LV008 chip requires special care.*/
  449. if ((vol.type == Am29LV008_FLASH) || (vol.type == Fuj29LV008_FLASH))
  450. if ((firstErasableBlock + iBlock) % (vol.chipSize / 0x10000l) == 0) {
  451. checkStatus(eraseFirstBlockLV008(&vol, firstErasableBlock + iBlock));
  452. continue;
  453. }
  454. /* No need to call mapBase because we know we are on a unit boundary */
  455. flashPtr = (FlashPTR)
  456. flMap(vol.socket,
  457. (firstErasableBlock + iBlock) * vol.erasableBlockSize);
  458. for (i = 0; i < vol.interleaving; i++) {
  459. amdCommand(&vol, i,SETUP_ERASE, flashPtr);
  460. tffsWriteByteFlash((FlashPTR) flAddLongToFarPointer((VOID FAR0 *)flashPtr,
  461. i + thisVars->unlockAddr1), UNLOCK_1);
  462. tffsWriteByteFlash((FlashPTR) flAddLongToFarPointer((VOID FAR0 *)flashPtr,
  463. i + thisVars->unlockAddr2), UNLOCK_2);
  464. tffsWriteByteFlash(flashPtr+i, SECTOR_ERASE);
  465. }
  466. do {
  467. #ifdef FL_BACKGROUND
  468. FLBoolean eraseSuspended = FALSE;
  469. while (flForeground(1) == BG_SUSPEND) { /* suspend */
  470. eraseSuspended = TRUE;
  471. for (i = 0; i < vol.interleaving; i++) {
  472. tffsWriteByteFlash(flashPtr+i, SUSPEND_ERASE);
  473. /* Wait for D6 to stop toggling */
  474. while ((tffsReadByteFlash(flashPtr+i) ^
  475. tffsReadByteFlash(flashPtr+i)) & D6)
  476. ;
  477. }
  478. }
  479. if (eraseSuspended) { /* resume */
  480. eraseSuspended = FALSE;
  481. for(i = 0; i < vol.interleaving; i++)
  482. tffsWriteByteFlash(flashPtr+i, RESUME_ERASE);
  483. }
  484. #endif
  485. finished = TRUE;
  486. for (i = 0; i < vol.interleaving; i++) {
  487. if (tffsReadByteFlash(flashPtr+i) != 0xff) {
  488. if ((tffsReadByteFlash(flashPtr+i) & D5) && tffsReadByteFlash(flashPtr+i) != 0xff) {
  489. tffsWriteByteFlash(flashPtr+i, READ_ARRAY);
  490. DEBUG_PRINT(("Debug: erase failed in AMD MTD.\n"));
  491. return flWriteFault;
  492. }
  493. finished = FALSE;
  494. flDelayMsecs(10);
  495. }
  496. }
  497. } while (!finished);
  498. }
  499. return flOK;
  500. }
  501. /*----------------------------------------------------------------------*/
  502. /* a m d M T D M a p */
  503. /* */
  504. /* Map through buffer. This routine will be registered as the map */
  505. /* routine for this MTD. */
  506. /* */
  507. /* Parameters: */
  508. /* vol : Pointer identifying drive */
  509. /* address : Flash address to be mapped. */
  510. /* length : number of bytes to map. */
  511. /* */
  512. /* Returns: */
  513. /* Pointer to the buffer data was mapped to. */
  514. /* */
  515. /*----------------------------------------------------------------------*/
  516. VOID FAR0 *amdMTDMap (FLFlash vol, CardAddress address, int length)
  517. {
  518. vol.socket->remapped = TRUE;
  519. return mapThroughBuffer(&vol,address,length);
  520. }
  521. /*----------------------------------------------------------------------*/
  522. /* a m d M T D R e a d */
  523. /* */
  524. /* Read some data from the flash. This routine will be registered as */
  525. /* the read routine for this MTD. */
  526. /* */
  527. /* Parameters: */
  528. /* vol : Pointer identifying drive */
  529. /* address : Address to read from. */
  530. /* buffer : buffer to read to. */
  531. /* length : number of bytes to read (up to sector size). */
  532. /* modes : EDC flag etc. */
  533. /* */
  534. /* Returns: */
  535. /* FLStatus : 0 on success, otherwise failed. */
  536. /* */
  537. /*----------------------------------------------------------------------*/
  538. FLStatus amdMTDRead(FLFlash vol,
  539. CardAddress address,
  540. VOID FAR1 *buffer,
  541. dword length,
  542. word modes)
  543. {
  544. ULONG i;
  545. UCHAR * byteBuffer;
  546. FlashPTR byteFlashPtr;
  547. ULONG * dwordBuffer = (ULONG *)buffer;
  548. FlashDPTR dwordFlashPtr = (FlashDPTR)flMap(vol.socket, address);
  549. for (i = 0; i < length - 4; i += 4, dwordBuffer++, dwordFlashPtr++) {
  550. *dwordBuffer = tffsReadDwordFlash(dwordFlashPtr);
  551. }
  552. byteBuffer = (UCHAR *)dwordBuffer;
  553. byteFlashPtr = (FlashPTR)dwordFlashPtr;
  554. for(; i < length; i++, byteBuffer++, byteFlashPtr++) {
  555. *byteBuffer = tffsReadByteFlash(byteFlashPtr);
  556. }
  557. return flOK ;
  558. }
  559. /*----------------------------------------------------------------------*/
  560. /* a m d M T D I d e n t i f y */
  561. /* */
  562. /* Identifies AMD and Fujitsu flash media and registers as an MTD for */
  563. /* such. */
  564. /* */
  565. /* On successful identification, the Flash structure is filled out and */
  566. /* the write and erase routines registered. */
  567. /* */
  568. /* Parameters: */
  569. /* vol : Pointer identifying drive */
  570. /* */
  571. /* Returns: */
  572. /* FLStatus : 0 on positive identificaion, failed otherwise */
  573. /*----------------------------------------------------------------------*/
  574. FLStatus amdMTDIdentify(FLFlash vol)
  575. {
  576. LONG inlv;
  577. DEBUG_PRINT(("Debug: entering AMD MTD identification routine.\n"));
  578. flSetWindowBusWidth(vol.socket,16);/* use 16-bits */
  579. flSetWindowSpeed(vol.socket,150); /* 120 nsec. */
  580. flSetWindowSize(vol.socket,2); /* 8 KBytes */
  581. vol.mtdVars = &mtdVars_amdmtd[flSocketNoOf(vol.socket)];
  582. thisVars->unlockAddr1 = NO_UNLOCK_ADDR;
  583. /* try different interleavings */
  584. for (inlv = 4; inlv > 0; inlv >>= 1) {
  585. if (inlv == 1)
  586. flSetWindowBusWidth(vol.socket,8); /* use 8-bits */
  587. vol.interleaving = (unsigned short)inlv;
  588. flIntelIdentify(&vol, amdCommand,0);
  589. if (vol.type == Am29F016_FLASH ||
  590. vol.type == Fuj29F016_FLASH ||
  591. vol.type == Am29F016C_FLASH ||
  592. vol.type == Fuj29F016C_FLASH ||
  593. vol.type == Am29F080_FLASH ||
  594. vol.type == Fuj29F080_FLASH ||
  595. vol.type == Am29LV080_FLASH ||
  596. vol.type == Fuj29LV080_FLASH ||
  597. vol.type == Am29LV008_FLASH ||
  598. vol.type == Fuj29LV008_FLASH ||
  599. vol.type == Am29F040_FLASH ||
  600. vol.type == Fuj29F040_FLASH ||
  601. vol.type == Am29LV017_FLASH ||
  602. vol.type == Fuj29LV017_FLASH)
  603. break;
  604. }
  605. if (vol.type == Am29F016_FLASH ||
  606. vol.type == Fuj29F016_FLASH ||
  607. vol.type == Am29F016C_FLASH ||
  608. vol.type == Fuj29F016C_FLASH ||
  609. vol.type == Am29LV017_FLASH ||
  610. vol.type == Fuj29LV017_FLASH)
  611. vol.chipSize = 0x200000l;
  612. else if (vol.type == Fuj29F080_FLASH ||
  613. vol.type == Am29F080_FLASH ||
  614. vol.type == Fuj29LV080_FLASH ||
  615. vol.type == Am29LV080_FLASH ||
  616. vol.type == Fuj29LV008_FLASH ||
  617. vol.type == Am29LV008_FLASH)
  618. vol.chipSize = 0x100000l;
  619. else if (vol.type == Fuj29F040_FLASH ||
  620. vol.type == Am29F040_FLASH)
  621. vol.chipSize = 0x80000l;
  622. else {
  623. DEBUG_PRINT(("Debug: did not identify AMD or Fujitsu flash media.\n"));
  624. return flUnknownMedia;
  625. }
  626. if ((vol.type == Am29F016C_FLASH) || (vol.type == Fuj29F016C_FLASH)) {
  627. thisVars->unlockAddr1 = thisVars->unlockAddr2 = 0L;
  628. thisVars->baseMask = 0xfffff800L * vol.interleaving;
  629. }
  630. else if ((vol.type == Am29F040_FLASH) || (vol.type == Fuj29F040_FLASH)){
  631. flSetWindowSize(vol.socket,8 * vol.interleaving);
  632. thisVars->unlockAddr1 = 0x5555u * vol.interleaving;
  633. thisVars->unlockAddr2 = 0x2aaau * vol.interleaving;
  634. thisVars->baseMask = 0xffff8000L * vol.interleaving;
  635. }
  636. else {
  637. thisVars->unlockAddr1 = 0x555 * vol.interleaving;
  638. thisVars->unlockAddr2 = 0x2aa * vol.interleaving;
  639. thisVars->baseMask = 0xfffff800L * vol.interleaving;
  640. }
  641. checkStatus(flIntelSize(&vol,amdCommand,0));
  642. vol.erasableBlockSize = 0x10000l * vol.interleaving;
  643. vol.flags |= SUSPEND_FOR_WRITE;
  644. /* Register our flash handlers */
  645. vol.write = amdMTDWrite;
  646. vol.erase = amdMTDErase;
  647. vol.map = amdMTDMap;
  648. vol.read = amdMTDRead;
  649. DEBUG_PRINT(("Debug: Identified AMD or Fujitsu flash media.\n"));
  650. return flOK;
  651. }
  652. /*----------------------------------------------------------------------*/
  653. /* f l R e g i s t e r A M D M T D */
  654. /* */
  655. /* Registers this MTD for use */
  656. /* */
  657. /* Parameters: */
  658. /* None */
  659. /* */
  660. /* Returns: */
  661. /* FLStatus : 0 on success, otherwise failure */
  662. /*----------------------------------------------------------------------*/
  663. FLStatus flRegisterAMDMTD(VOID)
  664. {
  665. if (noOfMTDs >= MTDS)
  666. return flTooManyComponents;
  667. mtdTable[noOfMTDs++] = amdMTDIdentify;
  668. return flOK;
  669. }