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.

550 lines
16 KiB

  1. /*
  2. * $Log: P:/user/amir/lite/vcs/i28f016.c_v $
  3. *
  4. * Rev 1.10 06 Oct 1997 9:45:48 danig
  5. * VPP functions under #ifdef
  6. *
  7. * Rev 1.9 10 Sep 1997 16:48:24 danig
  8. * Debug messages & got rid of generic names
  9. *
  10. * Rev 1.8 31 Aug 1997 15:09:20 danig
  11. * Registration routine return status
  12. *
  13. * Rev 1.7 24 Jul 1997 17:52:58 amirban
  14. * FAR to FAR0
  15. *
  16. * Rev 1.6 20 Jul 1997 17:17:06 amirban
  17. * No watchDogTimer
  18. *
  19. * Rev 1.5 07 Jul 1997 15:22:08 amirban
  20. * Ver 2.0
  21. *
  22. * Rev 1.4 04 Mar 1997 16:44:22 amirban
  23. * Page buffer bug fix
  24. *
  25. * Rev 1.3 18 Aug 1996 13:48:24 amirban
  26. * Comments
  27. *
  28. * Rev 1.2 12 Aug 1996 15:49:04 amirban
  29. * Added suspend/resume
  30. *
  31. * Rev 1.1 31 Jul 1996 14:30:50 amirban
  32. * Background stuff
  33. *
  34. * Rev 1.0 18 Jun 1996 16:34:30 amirban
  35. * Initial revision.
  36. */
  37. /************************************************************************/
  38. /* */
  39. /* FAT-FTL Lite Software Development Kit */
  40. /* Copyright (C) M-Systems Ltd. 1995-1996 */
  41. /* */
  42. /************************************************************************/
  43. /*----------------------------------------------------------------------*/
  44. /* */
  45. /* This MTD supports the following Flash technologies: */
  46. /* */
  47. /* - Intel 28F016SA/28016SV/Cobra 16-mbit devices */
  48. /* */
  49. /* And (among else), the following Flash media and cards: */
  50. /* */
  51. /* - Intel Series-2+ PCMCIA cards */
  52. /* */
  53. /*----------------------------------------------------------------------*/
  54. #include "flflash.h"
  55. #ifdef FL_BACKGROUND
  56. #include "backgrnd.h"
  57. #endif
  58. /* JEDEC ids for this MTD */
  59. #define I28F016_FLASH 0x89a0
  60. #define LH28F016SU_FLASH 0xB088
  61. #define SETUP_ERASE 0x2020
  62. #define SETUP_WRITE 0x4040
  63. #define CLEAR_STATUS 0x5050
  64. #define READ_STATUS 0x7070
  65. #define READ_ID 0x9090
  66. #define SUSPEND_ERASE 0xb0b0
  67. #define CONFIRM_ERASE 0xd0d0
  68. #define RESUME_ERASE 0xd0d0
  69. #define READ_ARRAY 0xffff
  70. #define LOAD_PAGE_BUFFER 0xe0e0
  71. #define WRITE_PAGE_BUFFER 0x0c0c
  72. #define READ_EXTENDED_REGS 0x7171
  73. #define WSM_VPP_ERROR 0x08
  74. #define WSM_ERROR 0x38
  75. #define WSM_SUSPENDED 0x40
  76. #define WSM_READY 0x80
  77. #define GSR_ERROR 0x20
  78. #define both(word) (vol.interleaving == 1 ? tffsReadWordFlash(word) : tffsReadWordFlash(word) & (tffsReadWordFlash(word) >> 8))
  79. #define any(word) (tffsReadWordFlash(word) | (tffsReadWordFlash(word) >> 8))
  80. /*----------------------------------------------------------------------*/
  81. /* i 2 8 f 0 1 6 W o r d S i z e */
  82. /* */
  83. /* Identify the card size for an Intel 28F016 word-mode Flash array. */
  84. /* Sets the value of vol.noOfChips. */
  85. /* */
  86. /* Parameters: */
  87. /* vol : Pointer identifying drive */
  88. /* */
  89. /* Returns: */
  90. /* FLStatus : 0 = OK, otherwise failed (invalid Flash array)*/
  91. /*----------------------------------------------------------------------*/
  92. FLStatus i28f016WordSize(FLFlash vol)
  93. {
  94. FlashWPTR flashPtr = (FlashWPTR) flMap(vol.socket,0);
  95. unsigned short id0, id1;
  96. tffsWriteWordFlash(flashPtr, CLEAR_STATUS);
  97. tffsWriteWordFlash(flashPtr, READ_ID);
  98. /* We leave the first chip in Read ID mode, so that we can */
  99. /* discover an address wraparound. */
  100. if( vol.type == I28F016_FLASH ) {
  101. id0 = 0x0089;
  102. id1 = 0x66a0;
  103. }
  104. else if( vol.type == LH28F016SU_FLASH ) {
  105. id0 = 0x00B0;
  106. id1 = 0x6688;
  107. }
  108. for (vol.noOfChips = 1; /* Scan the chips */
  109. vol.noOfChips < 2000; /* Big enough ? */
  110. vol.noOfChips++) {
  111. flashPtr = (FlashWPTR) flMap(vol.socket,vol.noOfChips * vol.chipSize);
  112. if (tffsReadWordFlash(flashPtr) == id0 && tffsReadWordFlash(flashPtr + 1) == id1)
  113. break; /* We've wrapped around to the first chip ! */
  114. tffsWriteWordFlash(flashPtr, READ_ID);
  115. if (!(tffsReadWordFlash(flashPtr) == id0 && tffsReadWordFlash(flashPtr + 1) == id1))
  116. break;
  117. tffsWriteWordFlash(flashPtr, CLEAR_STATUS);
  118. tffsWriteWordFlash(flashPtr, READ_ARRAY);
  119. }
  120. flashPtr = (FlashWPTR) flMap(vol.socket,0);
  121. tffsWriteWordFlash(flashPtr, READ_ARRAY);
  122. return flOK;
  123. }
  124. /*----------------------------------------------------------------------*/
  125. /* i 2 8 f 0 1 6 W r i t e */
  126. /* */
  127. /* Write a block of bytes to Flash */
  128. /* */
  129. /* This routine will be registered as the MTD flash.write routine */
  130. /* */
  131. /* Parameters: */
  132. /* vol : Pointer identifying drive */
  133. /* address : Card address to write to */
  134. /* buffer : Address of data to write */
  135. /* length : Number of bytes to write */
  136. /* overwrite : TRUE if overwriting old Flash contents */
  137. /* FALSE if old contents are known to be erased */
  138. /* */
  139. /* Returns: */
  140. /* FLStatus : 0 on success, failed otherwise */
  141. /*----------------------------------------------------------------------*/
  142. FLStatus i28f016Write(FLFlash vol,
  143. CardAddress address,
  144. const VOID FAR1 *buffer,
  145. dword length,
  146. word overwrite)
  147. {
  148. /* Set timeout of 5 seconds from now */
  149. ULONG writeTimeout = flMsecCounter + 5000;
  150. FLStatus status = flOK;
  151. FlashWPTR flashPtr;
  152. ULONG maxLength, i, from;
  153. UCHAR * bBuffer = (UCHAR *) buffer;
  154. FlashPTR bFlashPtr;
  155. ULONG * dBuffer = (ULONG *) buffer;
  156. FlashDPTR dFlashPtr;
  157. if (flWriteProtected(vol.socket))
  158. return flWriteProtect;
  159. if ((length & 1) || (address & 1)) /* Only write words on word-boundary */
  160. return flBadParameter;
  161. #ifdef SOCKET_12_VOLTS
  162. checkStatus(flNeedVpp(vol.socket));
  163. #endif
  164. maxLength = 256 * vol.interleaving;
  165. for (from = 0; from < length && status == flOK; from += maxLength) {
  166. FlashWPTR currPtr;
  167. ULONG lengthWord;
  168. ULONG tailBytes;
  169. ULONG thisLength = length - from;
  170. if (thisLength > maxLength)
  171. thisLength = maxLength;
  172. lengthWord = (thisLength + vol.interleaving - 1) /
  173. (vol.interleaving == 1 ? 2 : vol.interleaving) - 1;
  174. if (vol.interleaving != 1)
  175. lengthWord |= (lengthWord << 8);
  176. flashPtr = (FlashWPTR) flMap(vol.socket,address + from);
  177. tailBytes = ((thisLength - 1) & (vol.interleaving - 1)) + 1;
  178. for (i = 0, currPtr = flashPtr;
  179. i < (ULONG)vol.interleaving && i < thisLength;
  180. i += 2, currPtr++) {
  181. tffsWriteWordFlash(currPtr, LOAD_PAGE_BUFFER);
  182. if (i < tailBytes) {
  183. tffsWriteWordFlash(currPtr, (USHORT) lengthWord);
  184. }
  185. else {
  186. tffsWriteWordFlash(currPtr, (USHORT) (lengthWord - 1));
  187. }
  188. tffsWriteWordFlash(currPtr, 0);
  189. }
  190. dFlashPtr = (FlashDPTR) flashPtr;
  191. bFlashPtr = (FlashPTR) flashPtr;
  192. for (i = 0; i < thisLength - 4; i += 4) {
  193. tffsWriteDwordFlash(dFlashPtr + i, *(dBuffer + from + i));
  194. }
  195. for(; i < thisLength; i++) {
  196. tffsWriteByteFlash(bFlashPtr + i, *(bBuffer + from + i));
  197. }
  198. for (i = 0, currPtr = flashPtr;
  199. i < (ULONG)vol.interleaving && i < thisLength;
  200. i += 2, currPtr++) {
  201. tffsWriteWordFlash(currPtr, WRITE_PAGE_BUFFER);
  202. if (!((address + from + i) & vol.interleaving)) {
  203. /* Even address */
  204. tffsWriteWordFlash(currPtr, (USHORT) lengthWord);
  205. tffsWriteWordFlash(currPtr, 0);
  206. }
  207. else {
  208. /* Odd address */
  209. tffsWriteWordFlash(currPtr, 0);
  210. tffsWriteWordFlash(currPtr, (USHORT) lengthWord);
  211. }
  212. }
  213. /* map to the GSR & BSR */
  214. flashPtr = (FlashWPTR) flMap(vol.socket,
  215. (CardAddress)( (address + from & -(int)vol.erasableBlockSize) +
  216. 4 * vol.interleaving));
  217. for (i = 0, currPtr = flashPtr;
  218. i < (ULONG)vol.interleaving && i < thisLength;
  219. i += 2, currPtr++) {
  220. tffsWriteWordFlash(currPtr, READ_EXTENDED_REGS);
  221. while (!(both(currPtr) & WSM_READY) && flMsecCounter < writeTimeout)
  222. ;
  223. if ((any(currPtr) & GSR_ERROR) || !(both(currPtr) & WSM_READY)) {
  224. DEBUG_PRINT(("Debug: write failed for 16-bit Intel media.\n"));
  225. status = flWriteFault;
  226. tffsWriteWordFlash(currPtr, CLEAR_STATUS);
  227. }
  228. tffsWriteWordFlash(currPtr, READ_ARRAY);
  229. }
  230. }
  231. #ifdef SOCKET_12_VOLTS
  232. flDontNeedVpp(vol.socket);
  233. #endif
  234. /* verify the data */
  235. dFlashPtr = (FlashDPTR) flMap(vol.socket, address);
  236. dBuffer = (ULONG *) buffer;
  237. if (status == flOK) {
  238. /* compare double words */
  239. for (;length >= 4; length -= 4, dFlashPtr++, dBuffer++) {
  240. if (tffsReadDwordFlash(dFlashPtr) != *dBuffer) {
  241. DEBUG_PRINT(("Debug: write failed for 16-bit Intel media in verification.\n"));
  242. return flWriteFault;
  243. }
  244. }
  245. /* compare the last bytes */
  246. bFlashPtr = (FlashPTR) dFlashPtr;
  247. bBuffer = (UCHAR *)dBuffer;
  248. for (; length; length--, bFlashPtr++, bBuffer++) {
  249. if (tffsReadByteFlash(bFlashPtr) != *bBuffer) {
  250. DEBUG_PRINT(("Debug: write failed for 16-bit Intel media in verification.\n"));
  251. return flWriteFault;
  252. }
  253. }
  254. }
  255. return status;
  256. }
  257. /*----------------------------------------------------------------------*/
  258. /* i 2 8 f 0 1 6 E r a s e */
  259. /* */
  260. /* Erase one or more contiguous Flash erasable blocks */
  261. /* */
  262. /* This routine will be registered as the MTD vol.erase routine */
  263. /* */
  264. /* Parameters: */
  265. /* vol : Pointer identifying drive */
  266. /* firstErasableBlock : Number of first block to erase */
  267. /* numOfErasableBlocks: Number of blocks to erase */
  268. /* */
  269. /* Returns: */
  270. /* FLStatus : 0 on success, failed otherwise */
  271. /*----------------------------------------------------------------------*/
  272. FLStatus i28f016Erase(FLFlash vol,
  273. word firstErasableBlock,
  274. word numOfErasableBlocks)
  275. {
  276. FLStatus status = flOK; /* unless proven otherwise */
  277. LONG iBlock;
  278. if (flWriteProtected(vol.socket))
  279. return flWriteProtect;
  280. #ifdef SOCKET_12_VOLTS
  281. checkStatus(flNeedVpp(vol.socket));
  282. #endif
  283. for (iBlock = 0; iBlock < numOfErasableBlocks && status == flOK; iBlock++) {
  284. FlashWPTR currPtr;
  285. LONG i;
  286. FLBoolean finished;
  287. FlashWPTR flashPtr = (FlashWPTR)
  288. flMap(vol.socket,(firstErasableBlock + iBlock) * vol.erasableBlockSize);
  289. for (i = 0, currPtr = flashPtr;
  290. i < vol.interleaving;
  291. i += 2, currPtr++) {
  292. tffsWriteWordFlash(currPtr, SETUP_ERASE);
  293. tffsWriteWordFlash(currPtr, CONFIRM_ERASE);
  294. }
  295. do {
  296. #ifdef FL_BACKGROUND
  297. while (flForeground(1) == BG_SUSPEND) { /* suspend */
  298. for (i = 0, currPtr = flashPtr;
  299. i < vol.interleaving;
  300. i += 2, currPtr++) {
  301. tffsWriteWordFlash(currPtr, READ_STATUS);
  302. if (!(both(currPtr) & WSM_READY)) {
  303. tffsWriteWordFlash(currPtr, SUSPEND_ERASE);
  304. tffsWriteWordFlash(currPtr, READ_STATUS);
  305. while (!(both(currPtr) & WSM_READY))
  306. ;
  307. }
  308. tffsWriteWordFlash(currPtr, READ_ARRAY);
  309. }
  310. }
  311. #endif
  312. finished = TRUE;
  313. for (i = 0, currPtr = flashPtr;
  314. i < vol.interleaving;
  315. i += 2, currPtr++) {
  316. tffsWriteWordFlash(currPtr, READ_STATUS);
  317. if (any(currPtr) & WSM_SUSPENDED) {
  318. tffsWriteWordFlash(currPtr, RESUME_ERASE);
  319. finished = FALSE;
  320. }
  321. else if (!(both(currPtr) & WSM_READY))
  322. finished = FALSE;
  323. else {
  324. if (any(currPtr) & WSM_ERROR) {
  325. DEBUG_PRINT(("Debug: erase failed for 16-bit Intel media.\n"));
  326. status = (any(currPtr) & WSM_VPP_ERROR) ? flVppFailure : flWriteFault;
  327. tffsWriteWordFlash(currPtr, CLEAR_STATUS);
  328. }
  329. tffsWriteWordFlash(currPtr, READ_ARRAY);
  330. }
  331. }
  332. flDelayMsecs(10);
  333. } while (!finished);
  334. }
  335. #ifdef SOCKET_12_VOLTS
  336. flDontNeedVpp(vol.socket);
  337. #endif
  338. return status;
  339. }
  340. /*----------------------------------------------------------------------*/
  341. /* i 2 8 f 0 1 6 M a p */
  342. /* */
  343. /* Map through buffer. This routine will be registered as the map */
  344. /* routine for this MTD. */
  345. /* */
  346. /* Parameters: */
  347. /* vol : Pointer identifying drive */
  348. /* address : Flash address to be mapped. */
  349. /* length : number of bytes to map. */
  350. /* */
  351. /* Returns: */
  352. /* Pointer to the buffer data was mapped to. */
  353. /* */
  354. /*----------------------------------------------------------------------*/
  355. VOID FAR0 *i28f016Map (FLFlash vol, CardAddress address, int length)
  356. {
  357. vol.socket->remapped = TRUE;
  358. return mapThroughBuffer(&vol,address,length);
  359. }
  360. /*----------------------------------------------------------------------*/
  361. /* i 2 8 f 0 1 6 R e a d */
  362. /* */
  363. /* Read some data from the flash. This routine will be registered as */
  364. /* the read routine for this MTD. */
  365. /* */
  366. /* Parameters: */
  367. /* vol : Pointer identifying drive */
  368. /* address : Address to read from. */
  369. /* buffer : buffer to read to. */
  370. /* length : number of bytes to read (up to sector size). */
  371. /* modes : EDC flag etc. */
  372. /* */
  373. /* Returns: */
  374. /* FLStatus : 0 on success, otherwise failed. */
  375. /* */
  376. /*----------------------------------------------------------------------*/
  377. FLStatus i28f016Read(FLFlash vol,
  378. CardAddress address,
  379. VOID FAR1 *buffer,
  380. dword length,
  381. word modes)
  382. {
  383. ULONG i;
  384. UCHAR * bBuffer;
  385. FlashPTR bFlashPtr;
  386. ULONG * dBuffer = (ULONG *)buffer;
  387. FlashDPTR dFlashPtr = (FlashDPTR)flMap(vol.socket, address);
  388. for (i = 0; i < length - 4; i += 4, dBuffer++, dFlashPtr++) {
  389. *dBuffer = tffsReadDwordFlash(dFlashPtr);
  390. }
  391. bBuffer = (UCHAR *)dBuffer;
  392. bFlashPtr = (FlashPTR)dFlashPtr;
  393. for(; i < length; i++, bBuffer++, bFlashPtr++) {
  394. *bBuffer = tffsReadByteFlash(bFlashPtr);
  395. }
  396. return flOK ;
  397. }
  398. /*----------------------------------------------------------------------*/
  399. /* i 2 8 f 0 1 6 I d e n t i f y */
  400. /* */
  401. /* Identifies media based on Intel 28F016 and registers as an MTD for */
  402. /* such. */
  403. /* */
  404. /* This routine will be placed on the MTD list in custom.h. It must be */
  405. /* an extern routine. */
  406. /* */
  407. /* On successful identification, the Flash structure is filled out and */
  408. /* the write and erase routines registered. */
  409. /* */
  410. /* Parameters: */
  411. /* vol : Pointer identifying drive */
  412. /* */
  413. /* Returns: */
  414. /* FLStatus : 0 on positive identificaion, failed otherwise */
  415. /*----------------------------------------------------------------------*/
  416. FLStatus i28f016Identify(FLFlash vol)
  417. {
  418. FlashWPTR flashPtr;
  419. DEBUG_PRINT(("Debug: entering 16-bit Intel media identification routine.\n"));
  420. flSetWindowBusWidth(vol.socket,16);/* use 16-bits */
  421. flSetWindowSpeed(vol.socket,150); /* 120 nsec. */
  422. flSetWindowSize(vol.socket,2); /* 8 KBytes */
  423. flashPtr = (FlashWPTR) flMap(vol.socket,0);
  424. vol.noOfChips = 0;
  425. tffsWriteWordFlash(flashPtr, READ_ID);
  426. if (tffsReadWordFlash(flashPtr) == 0x0089 && tffsReadWordFlash(flashPtr + 1) == 0x66a0) {
  427. /* Word mode */
  428. vol.type = I28F016_FLASH;
  429. vol.interleaving = 1;
  430. tffsWriteWordFlash(flashPtr, READ_ARRAY);
  431. }
  432. else if (tffsReadWordFlash(flashPtr) == 0x00B0 && tffsReadWordFlash(flashPtr + 1) == 0x6688) {
  433. /* Word mode */
  434. vol.type = LH28F016SU_FLASH;
  435. vol.interleaving = 1;
  436. tffsWriteWordFlash(flashPtr, READ_ARRAY);
  437. }
  438. else {
  439. /* Use standard identification routine to detect byte-mode */
  440. flIntelIdentify(&vol, NULL,0);
  441. if (vol.interleaving == 1)
  442. vol.type = NOT_FLASH; /* We cannot handle byte-mode interleaving-1 */
  443. }
  444. if( (vol.type == I28F016_FLASH) || (vol.type == LH28F016SU_FLASH) ) {
  445. vol.chipSize = 0x200000L;
  446. vol.erasableBlockSize = 0x10000L * vol.interleaving;
  447. checkStatus(vol.interleaving == 1 ?
  448. i28f016WordSize(&vol) :
  449. flIntelSize(&vol, NULL,0));
  450. /* Register our flash handlers */
  451. vol.write = i28f016Write;
  452. vol.erase = i28f016Erase;
  453. vol.read = i28f016Read;
  454. vol.map = i28f016Map;
  455. DEBUG_PRINT(("Debug: identified 16-bit Intel media.\n"));
  456. return flOK;
  457. }
  458. else {
  459. DEBUG_PRINT(("Debug: failed to identify 16-bit Intel media.\n"));
  460. return flUnknownMedia; /* not ours */
  461. }
  462. }
  463. /*----------------------------------------------------------------------*/
  464. /* f l R e g i s t e r I 2 8 F 0 1 6 */
  465. /* */
  466. /* Registers this MTD for use */
  467. /* */
  468. /* Parameters: */
  469. /* None */
  470. /* */
  471. /* Returns: */
  472. /* FLStatus : 0 on success, otherwise failure */
  473. /*----------------------------------------------------------------------*/
  474. FLStatus flRegisterI28F016(VOID)
  475. {
  476. if (noOfMTDs >= MTDS)
  477. return flTooManyComponents;
  478. mtdTable[noOfMTDs++] = i28f016Identify;
  479. return flOK;
  480. }