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.

537 lines
15 KiB

  1. /*
  2. * $Log: V:/i28f008.c_v $
  3. *
  4. * Rev 1.16 06 Oct 1997 18:37:30 ANDRY
  5. * no COBUX
  6. *
  7. * Rev 1.15 05 Oct 1997 19:11:08 ANDRY
  8. * COBUX (Motorola M68360 16-bit only board)
  9. *
  10. * Rev 1.14 05 Oct 1997 14:35:36 ANDRY
  11. * flNeedVpp() and flDontNeedVpp() are under #ifdef SOCKET_12_VOLTS
  12. *
  13. * Rev 1.13 10 Sep 1997 16:18:10 danig
  14. * Got rid of generic names
  15. *
  16. * Rev 1.12 04 Sep 1997 18:47:20 danig
  17. * Debug messages
  18. *
  19. * Rev 1.11 31 Aug 1997 15:06:40 danig
  20. * Registration routine return status
  21. *
  22. * Rev 1.10 24 Jul 1997 17:52:30 amirban
  23. * FAR to FAR0
  24. *
  25. * Rev 1.9 21 Jul 1997 14:44:06 danig
  26. * No parallelLimit
  27. *
  28. * Rev 1.8 20 Jul 1997 17:17:00 amirban
  29. * No watchDogTimer
  30. *
  31. * Rev 1.7 07 Jul 1997 15:22:06 amirban
  32. * Ver 2.0
  33. *
  34. * Rev 1.6 15 Apr 1997 19:16:40 danig
  35. * Pointer conversions.
  36. *
  37. * Rev 1.5 29 Aug 1996 14:17:48 amirban
  38. * Warnings
  39. *
  40. * Rev 1.4 18 Aug 1996 13:48:44 amirban
  41. * Comments
  42. *
  43. * Rev 1.3 31 Jul 1996 14:31:10 amirban
  44. * Background stuff
  45. *
  46. * Rev 1.2 04 Jul 1996 18:20:06 amirban
  47. * New flag field
  48. *
  49. * Rev 1.1 03 Jun 1996 16:28:58 amirban
  50. * Cobra additions
  51. *
  52. * Rev 1.0 20 Mar 1996 13:33:06 amirban
  53. * Initial revision.
  54. */
  55. /************************************************************************/
  56. /* */
  57. /* FAT-FTL Lite Software Development Kit */
  58. /* Copyright (C) M-Systems Ltd. 1995-1996 */
  59. /* */
  60. /************************************************************************/
  61. /*----------------------------------------------------------------------*/
  62. /* */
  63. /* This MTD supports the following Flash technologies: */
  64. /* */
  65. /* - Intel 28F008/Cobra 8-mbit devices */
  66. /* - Intel 28F016SA/28016SV/Cobra 16-mbit devices (byte-mode operation) */
  67. /* */
  68. /* And (among else), the following Flash media and cards: */
  69. /* */
  70. /* - Intel Series-2 PCMCIA cards */
  71. /* - Intel Series-2+ PCMCIA cards */
  72. /* - M-Systems ISA/Tiny/PC-104 Flash Disks */
  73. /* - M-Systems NOR PCMCIA cards */
  74. /* - Intel Value-100 cards */
  75. /* */
  76. /*----------------------------------------------------------------------*/
  77. #include "flflash.h"
  78. #ifdef FL_BACKGROUND
  79. #include "backgrnd.h"
  80. #endif
  81. #define flash (*pFlash)
  82. #define SETUP_ERASE 0x20
  83. #define SETUP_WRITE 0x40
  84. #define CLEAR_STATUS 0x50
  85. #define READ_STATUS 0x70
  86. #define READ_ID 0x90
  87. #define SUSPEND_ERASE 0xb0
  88. #define CONFIRM_ERASE 0xd0
  89. #define RESUME_ERASE 0xd0
  90. #define READ_ARRAY 0xff
  91. #define WSM_ERROR 0x38
  92. #define WSM_VPP_ERROR 0x08
  93. #define WSM_SUSPENDED 0x40
  94. #define WSM_READY 0x80
  95. /* JEDEC ids for this MTD */
  96. #define I28F008_FLASH 0x89a2
  97. #define I28F016_FLASH 0x89a0
  98. #define COBRA004_FLASH 0x89a7
  99. #define COBRA008_FLASH 0x89a6
  100. #define COBRA016_FLASH 0x89aa
  101. #define MOBILE_MAX_INLV_4 0x8989
  102. #define LDP_1MB_IN_16BIT_MODE 0x89ff
  103. /* Definition of MTD specific vol.flags bits: */
  104. #define NO_12VOLTS 0x100 /* Card does not need 12 Volts Vpp */
  105. /*----------------------------------------------------------------------*/
  106. /* i 2 8 f 0 0 8 W r i t e */
  107. /* */
  108. /* Write a block of bytes to Flash */
  109. /* */
  110. /* This routine will be registered as the MTD vol.write routine */
  111. /* */
  112. /* Parameters: */
  113. /* vol : Pointer identifying drive */
  114. /* address : Card address to write to */
  115. /* buffer : Address of data to write */
  116. /* length : Number of bytes to write */
  117. /* overwrite : TRUE if overwriting old Flash contents */
  118. /* FALSE if old contents are known to be erased */
  119. /* */
  120. /* Returns: */
  121. /* FLStatus : 0 on success, failed otherwise */
  122. /*----------------------------------------------------------------------*/
  123. FLStatus i28f008Write(FLFlash vol,
  124. CardAddress address,
  125. const VOID FAR1 *buffer,
  126. dword length,
  127. word overwrite)
  128. {
  129. /* Set timeout ot 5 seconds from now */
  130. ULONG writeTimeout = flMsecCounter + 5000;
  131. FLStatus status;
  132. ULONG i, cLength;
  133. FlashPTR flashPtr;
  134. if (flWriteProtected(vol.socket))
  135. return flWriteProtect;
  136. #ifdef SOCKET_12_VOLTS
  137. if (!(vol.flags & NO_12VOLTS))
  138. checkStatus(flNeedVpp(vol.socket));
  139. #endif
  140. flashPtr = (FlashPTR) flMap(vol.socket,address);
  141. cLength = length;
  142. if (vol.interleaving == 1) {
  143. lastByte:
  144. #ifdef __cplusplus
  145. #define bFlashPtr flashPtr
  146. #define bBuffer ((const UCHAR FAR1 * &) buffer)
  147. #else
  148. #define bFlashPtr flashPtr
  149. #define bBuffer ((const UCHAR FAR1 *) buffer)
  150. #endif
  151. while (cLength >= 1) {
  152. tffsWriteByteFlash(bFlashPtr, SETUP_WRITE);
  153. tffsWriteByteFlash(bFlashPtr, *bBuffer);
  154. cLength--;
  155. bBuffer++;
  156. bFlashPtr++;
  157. while (!(tffsReadByteFlash(bFlashPtr-1) & WSM_READY) && flMsecCounter < writeTimeout)
  158. ;
  159. }
  160. }
  161. else if (vol.interleaving == 2) {
  162. lastWord:
  163. #ifdef __cplusplus
  164. #define wFlashPtr ((FlashWPTR &) flashPtr)
  165. #define wBuffer ((const USHORT FAR1 * &) buffer)
  166. #else
  167. #define wFlashPtr ((FlashWPTR) flashPtr)
  168. #define wBuffer ((const USHORT FAR1 *) buffer)
  169. #endif
  170. while (cLength >= 2) {
  171. tffsWriteWordFlash(wFlashPtr, SETUP_WRITE * 0x101);
  172. tffsWriteWordFlash(wFlashPtr, *wBuffer);
  173. cLength -= 2;
  174. wBuffer++;
  175. wFlashPtr++;
  176. while ((~(tffsReadWordFlash(wFlashPtr-1)) & (WSM_READY * 0x101)) && flMsecCounter < writeTimeout)
  177. ;
  178. }
  179. if (cLength > 0)
  180. goto lastByte;
  181. }
  182. else /* if (vol.interleaving >= 4) */ {
  183. #ifdef __cplusplus
  184. #define dFlashPtr ((FlashDPTR &) flashPtr)
  185. #define dBuffer ((const ULONG FAR1 * &) buffer)
  186. #else
  187. #define dFlashPtr ((FlashDPTR) flashPtr)
  188. #define dBuffer ((const ULONG FAR1 *) buffer)
  189. #endif
  190. while (cLength >= 4) {
  191. tffsWriteDwordFlash(dFlashPtr, SETUP_WRITE * 0x1010101l);
  192. tffsWriteDwordFlash(dFlashPtr, *dBuffer);
  193. cLength -= 4;
  194. dBuffer++;
  195. dFlashPtr++;
  196. while ((~(tffsReadDwordFlash(dFlashPtr-1)) & (WSM_READY * 0x1010101lu)) && flMsecCounter < writeTimeout)
  197. ;
  198. }
  199. if (cLength > 0)
  200. goto lastWord;
  201. }
  202. flashPtr -= length;
  203. bBuffer -= length;
  204. status = flOK;
  205. for (i = 0; i < (ULONG)vol.interleaving && i < length; i++) {
  206. if (tffsReadByteFlash(flashPtr + i) & WSM_ERROR) {
  207. DEBUG_PRINT(("Debug: write failed for 8-bit Intel media.\n"));
  208. status = (tffsReadByteFlash(flashPtr + i) & WSM_VPP_ERROR) ? flVppFailure : flWriteFault;
  209. tffsWriteByteFlash(flashPtr + i, CLEAR_STATUS);
  210. }
  211. tffsWriteByteFlash(flashPtr + i, READ_ARRAY);
  212. }
  213. #ifdef SOCKET_12_VOLTS
  214. if (!(vol.flags & NO_12VOLTS))
  215. flDontNeedVpp(vol.socket);
  216. #endif
  217. /* verify the data */
  218. if (status == flOK) {
  219. /* compare double words */
  220. for (;length >= 4; length -= 4, dFlashPtr++, dBuffer++) {
  221. if (tffsReadDwordFlash(dFlashPtr) != *dBuffer) {
  222. DEBUG_PRINT(("Debug: write failed for 8-bit Intel media in verification.\n"));
  223. return flWriteFault;
  224. }
  225. }
  226. /* compare the last bytes */
  227. for (; length; length--, bFlashPtr++, bBuffer++) {
  228. if (tffsReadByteFlash(bFlashPtr) != *bBuffer) {
  229. DEBUG_PRINT(("Debug: write failed for 8-bit Intel media in verification.\n"));
  230. return flWriteFault;
  231. }
  232. }
  233. }
  234. return status;
  235. }
  236. /*----------------------------------------------------------------------*/
  237. /* i 2 8 f 0 0 8 E r a s e */
  238. /* */
  239. /* Erase one or more contiguous Flash erasable blocks */
  240. /* */
  241. /* This routine will be registered as the MTD vol.erase routine */
  242. /* */
  243. /* Parameters: */
  244. /* vol : Pointer identifying drive */
  245. /* firstErasableBlock : Number of first block to erase */
  246. /* numOfErasableBlocks: Number of blocks to erase */
  247. /* */
  248. /* Returns: */
  249. /* FLStatus : 0 on success, failed otherwise */
  250. /*----------------------------------------------------------------------*/
  251. FLStatus i28f008Erase(FLFlash vol,
  252. word firstErasableBlock,
  253. word numOfErasableBlocks)
  254. {
  255. LONG iBlock;
  256. FLStatus status = flOK; /* unless proven otherwise */
  257. if (flWriteProtected(vol.socket))
  258. return flWriteProtect;
  259. #ifdef SOCKET_12_VOLTS
  260. if (!(vol.flags & NO_12VOLTS))
  261. checkStatus(flNeedVpp(vol.socket));
  262. #endif
  263. for (iBlock = 0; iBlock < numOfErasableBlocks && status == flOK; iBlock++) {
  264. LONG j;
  265. FLBoolean finished;
  266. FlashPTR flashPtr = (FlashPTR)
  267. flMap(vol.socket,
  268. (firstErasableBlock + iBlock) * vol.erasableBlockSize);
  269. for (j = 0; j < vol.interleaving; j++) {
  270. tffsWriteByteFlash(flashPtr + j, SETUP_ERASE);
  271. tffsWriteByteFlash(flashPtr + j, CONFIRM_ERASE);
  272. }
  273. do {
  274. #ifdef FL_BACKGROUND
  275. while (flForeground(1) == BG_SUSPEND) { /* suspend */
  276. for (j = 0; j < vol.interleaving; j++) {
  277. tffsWriteByteFlash(flashPtr + j, READ_STATUS);
  278. if (!(tffsReadByteFlash(flashPtr + j) & WSM_READY)) {
  279. tffsWriteByteFlash(flashPtr + j, SUSPEND_ERASE);
  280. tffsWriteByteFlash(flashPtr + j, READ_STATUS);
  281. while (!(tffsReadByteFlash(flashPtr + j) & WSM_READY))
  282. ;
  283. }
  284. tffsWriteByteFlash(flashPtr + j, READ_ARRAY);
  285. }
  286. }
  287. #endif
  288. finished = TRUE;
  289. for (j = 0; j < vol.interleaving; j++) {
  290. tffsWriteByteFlash(flashPtr + j, READ_STATUS);
  291. if (tffsReadByteFlash(flashPtr + j) & WSM_SUSPENDED) {
  292. tffsWriteByteFlash(flashPtr + j, RESUME_ERASE);
  293. finished = FALSE;
  294. }
  295. else if (!(tffsReadByteFlash(flashPtr + j) & WSM_READY))
  296. finished = FALSE;
  297. else {
  298. if (tffsReadByteFlash(flashPtr + j) & WSM_ERROR) {
  299. DEBUG_PRINT(("Debug: erase failed for 8-bit Intel media.\n"));
  300. status = (tffsReadByteFlash(flashPtr + j) & WSM_VPP_ERROR) ? flVppFailure : flWriteFault;
  301. tffsWriteByteFlash(flashPtr + j, CLEAR_STATUS);
  302. }
  303. tffsWriteByteFlash(flashPtr + j, READ_ARRAY);
  304. }
  305. flDelayMsecs(10);
  306. }
  307. } while (!finished);
  308. } /* block loop */
  309. #ifdef SOCKET_12_VOLTS
  310. if (!(vol.flags & NO_12VOLTS))
  311. flDontNeedVpp(vol.socket);
  312. #endif
  313. return status;
  314. }
  315. /*----------------------------------------------------------------------*/
  316. /* i 2 8 f 0 0 8 M a p */
  317. /* */
  318. /* Map through buffer. This routine will be registered as the map */
  319. /* routine for this MTD. */
  320. /* */
  321. /* Parameters: */
  322. /* vol : Pointer identifying drive */
  323. /* address : Flash address to be mapped. */
  324. /* length : number of bytes to map. */
  325. /* */
  326. /* Returns: */
  327. /* Pointer to the buffer data was mapped to. */
  328. /* */
  329. /*----------------------------------------------------------------------*/
  330. VOID FAR0 *i28f008Map (FLFlash vol, CardAddress address, int length)
  331. {
  332. vol.socket->remapped = TRUE;
  333. return mapThroughBuffer(&vol,address,length);
  334. }
  335. /*----------------------------------------------------------------------*/
  336. /* i 2 8 f 0 0 8 R e a d */
  337. /* */
  338. /* Read some data from the flash. This routine will be registered as */
  339. /* the read routine for this MTD. */
  340. /* */
  341. /* Parameters: */
  342. /* vol : Pointer identifying drive */
  343. /* address : Address to read from. */
  344. /* buffer : buffer to read to. */
  345. /* length : number of bytes to read (up to sector size). */
  346. /* modes : EDC flag etc. */
  347. /* */
  348. /* Returns: */
  349. /* FLStatus : 0 on success, otherwise failed. */
  350. /* */
  351. /*----------------------------------------------------------------------*/
  352. FLStatus i28f008Read(FLFlash vol,
  353. CardAddress address,
  354. VOID FAR1 *buffer,
  355. dword length,
  356. word modes)
  357. {
  358. ULONG i;
  359. UCHAR * byteBuffer;
  360. FlashPTR byteFlashPtr;
  361. ULONG * dwordBuffer = (ULONG *)buffer;
  362. FlashDPTR dwordFlashPtr = (FlashDPTR)flMap(vol.socket, address);
  363. for (i = 0; i < length - 4; i += 4, dwordBuffer++, dwordFlashPtr++) {
  364. *dwordBuffer = tffsReadDwordFlash(dwordFlashPtr);
  365. }
  366. byteBuffer = (UCHAR *)dwordBuffer;
  367. byteFlashPtr = (FlashPTR)dwordFlashPtr;
  368. for(; i < length; i++, byteBuffer++, byteFlashPtr++) {
  369. *byteBuffer = tffsReadByteFlash(byteFlashPtr);
  370. }
  371. return flOK ;
  372. }
  373. /*----------------------------------------------------------------------*/
  374. /* i 2 8 f 0 0 8 I d e n t i f y */
  375. /* */
  376. /* Identifies media based on Intel 28F008 and Intel 28F016 and */
  377. /* registers as an MTD for such */
  378. /* */
  379. /* This routine will be placed on the MTD list in custom.h. It must be */
  380. /* an extern routine. */
  381. /* */
  382. /* On successful identification, the Flash structure is filled out and */
  383. /* the write and erase routines registered. */
  384. /* */
  385. /* Parameters: */
  386. /* vol : Pointer identifying drive */
  387. /* */
  388. /* Returns: */
  389. /* FLStatus : 0 on positive identificaion, failed otherwise */
  390. /*----------------------------------------------------------------------*/
  391. FLStatus i28f008Identify(FLFlash vol)
  392. {
  393. LONG iChip;
  394. CardAddress idOffset = 0;
  395. DEBUG_PRINT(("Debug: i28f008Identify :entering 8-bit Intel media identification routine.\n"));
  396. flSetWindowBusWidth(vol.socket, 16);/* use 16-bits */
  397. flSetWindowSpeed(vol.socket, 150); /* 120 nsec. */
  398. flSetWindowSize(vol.socket, 2); /* 8 KBytes */
  399. flIntelIdentify(&vol, NULL,0);
  400. if (vol.type == NOT_FLASH) {
  401. /* The flash may be write-protected at offset 0. Try another offset */
  402. idOffset = 0x80000l;
  403. flIntelIdentify(&vol, NULL,idOffset);
  404. }
  405. if (vol.type == LDP_1MB_IN_16BIT_MODE) {
  406. flSetWindowBusWidth(vol.socket, 8); /* use 8-bits */
  407. flIntelIdentify(&vol, NULL,idOffset); /* and try to get a valid id */
  408. }
  409. switch (vol.type) {
  410. case COBRA004_FLASH:
  411. vol.chipSize = 0x80000l;
  412. vol.flags |= SUSPEND_FOR_WRITE | NO_12VOLTS;
  413. break;
  414. case COBRA008_FLASH:
  415. vol.flags |= SUSPEND_FOR_WRITE | NO_12VOLTS;
  416. /* no break */
  417. case MOBILE_MAX_INLV_4:
  418. case I28F008_FLASH:
  419. vol.chipSize = 0x100000l;
  420. break;
  421. case COBRA016_FLASH:
  422. vol.flags |= SUSPEND_FOR_WRITE | NO_12VOLTS;
  423. /* no break */
  424. case I28F016_FLASH:
  425. vol.chipSize = 0x200000l;
  426. break;
  427. default:
  428. DEBUG_PRINT(("Debug: failed to identify 8-bit Intel media.\n"));
  429. return flUnknownMedia; /* not ours */
  430. }
  431. vol.erasableBlockSize = 0x10000l * vol.interleaving;
  432. checkStatus(flIntelSize(&vol, NULL,idOffset));
  433. if (vol.type == MOBILE_MAX_INLV_4)
  434. vol.type = I28F008_FLASH;
  435. for (iChip = 0; iChip < vol.noOfChips; iChip += vol.interleaving) {
  436. LONG i;
  437. FlashPTR flashPtr = (FlashPTR)
  438. flMap(vol.socket,iChip * vol.chipSize);
  439. for (i = 0; i < vol.interleaving; i++)
  440. tffsWriteByteFlash(flashPtr + i, CLEAR_STATUS);
  441. }
  442. /* Register our flash handlers */
  443. vol.write = i28f008Write;
  444. vol.erase = i28f008Erase;
  445. vol.read = i28f008Read;
  446. vol.map = i28f008Map;
  447. DEBUG_PRINT(("Debug: i28f008Identify :identified 8-bit Intel media.\n"));
  448. return flOK;
  449. }
  450. /*----------------------------------------------------------------------*/
  451. /* f l R e g i s t e r I 2 8 F 0 0 8 */
  452. /* */
  453. /* Registers this MTD for use */
  454. /* */
  455. /* Parameters: */
  456. /* None */
  457. /* */
  458. /* Returns: */
  459. /* FLStatus : 0 on success, otherwise failure */
  460. /*----------------------------------------------------------------------*/
  461. FLStatus flRegisterI28F008(VOID)
  462. {
  463. if (noOfMTDs >= MTDS)
  464. return flTooManyComponents;
  465. mtdTable[noOfMTDs++] = i28f008Identify;
  466. return flOK;
  467. }