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.

4081 lines
175 KiB

  1. /*
  2. * $Log: V:/Flite/archives/TrueFFS5/Src/MDOCPLUS.C_V $
  3. *
  4. * Rev 1.45 Apr 15 2002 07:37:38 oris
  5. * Changed usage and logic of checkToggle to be more intuitive.
  6. * Added support for new access layer (docsys). MTD now initializes the access layer accessing the DiskOnChip registers.
  7. * Added macro's for several special DiskOnChip registers.
  8. * Remove interleave if statement since new access layer simply uses different routine for int-1 and int-2.
  9. * Bug fix - setAsicMode routine should first exit power down before checking for access error.
  10. * Bug fix - forceDownload routine did not issue the download command to all DiskOnChip floors.
  11. * Bug fix - added verify write support for uneven address and length.
  12. * Bug fix - doc2write routine might not report flHWProtection when in FL_OFF mode.
  13. * Bug fix - readBBT when reading less then 8 bytes.
  14. * Bug fix - writeIPL routine did not write all copies of IPL
  15. * Bug fix - readIPL routine did not set Max Id properly.
  16. *
  17. * Rev 1.44 Feb 19 2002 21:00:40 oris
  18. * Replaced flTimeOut status with flTimedOut.
  19. * Bug fix - missing initialization of returned status in otpSize routine.
  20. * Bug fix - read OTP routine when offset != 0
  21. * Bug fix - unique ID is now read with EDC.
  22. *
  23. * Rev 1.43 Jan 29 2002 20:09:40 oris
  24. * Switched arguments sent to docPlusSet.
  25. * Added support for FL_IPL_MODE_XSCALE and changed support for FL_IPL_MODE_SA in writeIPL routine acording to new spec.
  26. * Added sanity check for write IPL modes.
  27. *
  28. * Rev 1.42 Jan 28 2002 21:26:06 oris
  29. * Removed the use of back-slashes in macro definitions.
  30. * Changed docwrite and docset calls to separate DiskOnChip base window pointer and IO registers offset (for address shifting).
  31. * Replaced FLFlash argument with DiskOnChip memory base pointer in calls to docwrite , docset , docread, wrBuf and wrSet.
  32. * Removed win_io initialization (one of FLFlash record fields).
  33. * Improved check for flSuspend.
  34. * Added FL_IPL_DOWNLOAD flag to writeIPL routine in order to control whether the IPL will be reloaded after the update.
  35. * Removed wrBuf and wrSet macros.
  36. *
  37. * Rev 1.41 Jan 23 2002 23:33:38 oris
  38. * Bug fix - checkErase routine was unreasonably slow.
  39. * Changed DFORMAT_PRINT syntax
  40. * Bug fix - bad offset of writeIPL routine caused only first 512 bytes to be written.
  41. * Changed readOTP not to use PARTIAL_EDC code.
  42. *
  43. * Rev 1.40 Jan 21 2002 20:45:12 oris
  44. * Compilation errors for MTD_STANDALONE with BDK_VERIFY_WRITE.
  45. * Missing casting causes compilation error in readIPL.
  46. *
  47. * Rev 1.39 Jan 20 2002 20:57:02 oris
  48. * physicalToPointer was called with wrong size argument.
  49. *
  50. * Rev 1.38 Jan 20 2002 20:28:58 oris
  51. * Removed warnings.
  52. * Restored readIPL function initialization.
  53. *
  54. * Rev 1.37 Jan 20 2002 12:12:26 oris
  55. * Removed warnings.
  56. *
  57. * Rev 1.36 Jan 20 2002 10:10:52 oris
  58. * Moved mtdVars to docsoc.c (common with diskonc.c)
  59. * Removed warnings.
  60. * Replaced vol with *flash.
  61. * Removed flPreInitXXXX memory access routines.
  62. * Added new memory access routine implementation.
  63. * Simplified docsys interleave-1 operations (interleave-1 operations use only 1 byte per operation. The if was made in docsys and is now a part of the MTD)
  64. * Bug in implementation of VERIFY_ERASE extra area was fixed.
  65. * Added support for flSuspendMode environment variable.
  66. * Added support for 16MB Plus DiskOnChip :
  67. * - Revised write IPL code
  68. * - Revised read IPL code - now reads from SRAM and not flash causes download of protection logic.
  69. * - OTP / Unique ID offsets were updated to be interleave dependent.
  70. * - readBBT routine was changed to support DiskOnChip Millennium Plus.
  71. * - Identification routine was changed.
  72. * Changed checkStatus with if != flOK
  73. * Added interrupt support under ifdef (ENABLE_EDGE__INTERRUPT / ENABLE_LEVEL__INTERRUPT)
  74. * Changed NO_READ_BBT_CODE ifdef to MTD_READ_BBT.
  75. * Big fix in erasable Block Size Bits field of the flash record when changing interleave.
  76. * Added force remmapping of internal sector buffer.
  77. *
  78. * Rev 1.35 Nov 22 2001 19:48:46 oris
  79. * Power consumption bug fix - chip select to the flash was remained open causing the power down mode to be ignored and the ideal current consumption to be twice the normal current.
  80. * Made sure that when preventing the BUSY# signal to be asserted by the download operation all other bits of the output controll register remain as they were.
  81. *
  82. * Rev 1.34 Nov 21 2001 11:38:14 oris
  83. * Changed FL_WITH_VERIFY_WRITE and FL_WITHOUT_VERIFY_WRITE to FL_ON and FL_OFF.
  84. *
  85. * Rev 1.33 Nov 20 2001 20:25:36 oris
  86. * Bug fix - deep power down mode was released after access due to check of access error.
  87. * Bug fix - download operation did assert the BUSY#.
  88. *
  89. * Rev 1.32 Nov 16 2001 00:23:04 oris
  90. * Restored byte (if_cfg=8) access for reading syndrome registers.
  91. *
  92. * Rev 1.31 Nov 08 2001 10:49:48 oris
  93. * Removed warnings.
  94. * Added run-time control over verify write mode buffers.
  95. *
  96. * Rev 1.30 Oct 18 2001 22:17:22 oris
  97. * Bug fix - incorrect read and write when performed from the middle of the page, incomplete pages , more then 1k when EDC is not requested.
  98. *
  99. * Rev 1.29 Oct 11 2001 23:55:10 oris
  100. * Bug fix - Read operation to the MTD from 2 different pages (for example read operation to BDK with length > 1K) the logic that determined whether to read the last data from the pipeline is incorrect.
  101. *
  102. * 1) When reading with EDC data will be read from the I/O registers and not from the pipeline - This is not a problem, since the pipeline is not necessary.
  103. * 2) When reading without EDC data will be read both from the I/O registers and from the pipeline casing overwriting the last 2 bytes with 0xff.
  104. *
  105. * Rev 1.28 Oct 10 2001 19:48:02 oris
  106. * Bug fix - WORD_ADD_FAR macro was misused using casing bad casting to unaligned buffers. Replaced it with read operation to an intermidiate variable and then copy byte after byte.
  107. *
  108. * Rev 1.27 Sep 24 2001 18:24:08 oris
  109. * Removed warnings.
  110. * Added support for readBBT call for less then 8 bytes.
  111. * Removed DOC_PLUS_ACCESS_TYPE ifdef.
  112. *
  113. * Rev 1.26 Sep 15 2001 23:47:20 oris
  114. * Placed YIELD_CPU definition under ifdef to prevent redeclaration.
  115. * Changed doc2erase to support up to 64K erase blocks.
  116. * Added reconstruct flag to readBBT routine - stating whether to reconstruct BBT if it is not available.
  117. * Changed all memory access routine to DiskOnChip Millennium Plus dedicated routines.
  118. * Changed recoverFromAccessError and setAsicMode routine to use standard memory access routines and not preInit routines.
  119. * Bug fix - read\write from uneven address.
  120. * Bug fix - read full 1k with no EDC.
  121. * Bug fix - first 4 blocks are not reported correctly by the readBBT()
  122. * Added debug print when BBT is not read well.
  123. *
  124. * Rev 1.25 Jul 29 2001 19:15:30 oris
  125. * Changed file calls to macros.
  126. *
  127. * Rev 1.24 Jul 13 2001 01:08:08 oris
  128. * Bug fix - rewritten VERIFY_WRITE compilation option.
  129. * Prevent calls to docPlusRead with 0 length.
  130. * Bug fix - added support for platforms that can not access single bytes.
  131. * Added PARTIAL_EDC read flag to the read routine.
  132. * Revised checkErase routine to include extra area.
  133. * Bug fix - missing check of write protection in doc2erase.
  134. * Bug fix - read bbt .
  135. * Insert key before writing IPL since it might be protected with the default protection.
  136. * Bug fix - set floor to 0 in all OTP calls.
  137. * Use PARTIAL_EDC in read OTP routine.
  138. * Added initialization of max erase cycles FLFlash field.
  139. *
  140. * Rev 1.23 Jun 17 2001 16:39:10 oris
  141. * Improved documentation and remove warnings.
  142. *
  143. * Rev 1.22 Jun 17 2001 08:17:52 oris
  144. * Bug fix - caused changing to interleave 1 even if already in this mode.
  145. * Changed NO_READ_BBT_CODE to MTD_NO_READ_BBT_CODE.
  146. *
  147. * Rev 1.21 May 30 2001 21:16:06 oris
  148. * Bug fix - pages per blocks might be used uninitialized.
  149. *
  150. * Rev 1.20 May 17 2001 19:21:10 oris
  151. * Removed warnings.
  152. *
  153. * Rev 1.19 May 16 2001 21:20:34 oris
  154. * Added failsafe mechanism for the download operation.
  155. * Changed code variable name to flCode (avoid name clashes).
  156. * Bug fix - read operation from extra area of second sector of page starting from offset 6 reading more then 2 bytes.
  157. * Bug fix - write OTP and read OTP routines - Wrong usage of buffers.
  158. * Removed warnings.
  159. * Bug fix - enable power down routine while in MTD_STANDALONE mode.
  160. *
  161. * Rev 1.18 May 09 2001 00:33:12 oris
  162. * Changed IPL_CODE to NO_IPL_CODE , READ_BBT_CODE to NO_READ_BBT_CODE.
  163. * Made sure that forceddownload is active when HW_OTP compilation flag is defined.
  164. * Removed 2 redundant ALE down calls.
  165. * Change all 2 consequative read operation to for in order to prevent compiler optimizations.
  166. *
  167. * Rev 1.17 May 06 2001 22:41:52 oris
  168. * Bug fix - checking for access error was moved. After every set address operation and after erase confirm.
  169. * Bug fix - readBBT for unaligned units.
  170. * Removed warnings.
  171. * redundant was misspelled.
  172. *
  173. * Rev 1.16 May 02 2001 07:29:50 oris
  174. * flInterleaveError was misspelled.
  175. * Added the BBT_UNAVAIL_UNIT defintion.
  176. *
  177. * Rev 1.15 May 01 2001 14:22:56 oris
  178. * Bug fix - reading BBT of cascaded device.
  179. *
  180. * Rev 1.14 Apr 30 2001 18:01:54 oris
  181. * Bug fix - Several ifdef caused exception since MTD buffer was not allocated.
  182. * Use erasableBlockSizeBits instead of erasableBlockSize when posible.
  183. * Added EDC check when reading the BBT.
  184. * Removed warrnings.
  185. *
  186. * Rev 1.13 Apr 24 2001 17:11:14 oris
  187. * Bug fix - Wrong data when reading 2 bytes from data area.
  188. * Removed compilation problems when USE_FUNC is defined.
  189. * Bug fix - read\write operation with the EDC flags ignored the EXTRA flag.
  190. * Bug fix - ipl and otp routines causes exception in MTD_STANDALONE mode.
  191. * Rebuild OTP routine.
  192. *
  193. * Rev 1.12 Apr 18 2001 21:24:54 oris
  194. * Bug fix - bad status code when writting in interleave - 1 fails, because changeInterleave routine is called while in access error.
  195. * Bug fix - removed download operation after write IPL.
  196. * Bug fix - Fixed casting problem in flash type identification.
  197. * Bug fix - Bad status code in doc2erase.
  198. * Bug fix - OTP area written\ read in interleave - 1
  199. * Bug fix - bad endian handling in OTP routines.
  200. * Moved forced download routine from under the MTD_STANDALONE compilation flag.
  201. * Removed warrnings.
  202. *
  203. * Rev 1.11 Apr 18 2001 11:17:30 oris
  204. * Bug fix in getUniqueId routine.
  205. *
  206. * Rev 1.10 Apr 18 2001 09:27:38 oris
  207. * Removed warrnings.
  208. *
  209. * Rev 1.9 Apr 16 2001 21:46:58 oris
  210. * Bug fix - aliasing mechanism fixed.
  211. *
  212. * Rev 1.8 Apr 16 2001 13:54:34 oris
  213. * Removed warrnings.
  214. * Bug fix - uninitialized buffer in read operation from uneven address.
  215. * Bug fix - report hw protection fault on write and erase operations.
  216. *
  217. * Rev 1.7 Apr 12 2001 06:52:06 oris
  218. * Added setFloor in chkAsicMode in order to make sure floor does not change.
  219. * Added powerDown routine and registration.
  220. * Added download routine registration.
  221. * Added support for reading and writing uneven address or length.
  222. * Removed warrnings.
  223. * Bug fix for memory lick in readBBT.
  224. * Changed several routines to static.
  225. *
  226. * Rev 1.6 Apr 10 2001 23:55:30 oris
  227. * Bug fix - in readbbt routine buffer was not incremented correctly.
  228. *
  229. * Rev 1.5 Apr 10 2001 16:43:14 oris
  230. * Added multiple floor support for readbbt routine.
  231. * Added call for docSocketInit which initializes the socket routines.
  232. * Added validity check after flMap call in order to support pccard premoutn routine.
  233. *
  234. * Rev 1.4 Apr 09 2001 19:02:34 oris
  235. * Removed unused variables.
  236. * Bug fix on erase operation to more then 1 unit.
  237. * Comment forced download in device identification routine.
  238. *
  239. */
  240. /*********************************************************************/
  241. /* */
  242. /* FAT-FTL Lite Software Development Kit */
  243. /* Copyright (C) M-Systems Ltd. 1995-2001 */
  244. /* */
  245. /*********************************************************************/
  246. /*********************************************************************
  247. * *
  248. * DESCRIPTION: basic mtd functions for MDOC32 *
  249. * interleave 1 *
  250. * page organization : *
  251. * 512 bytes data sector 0, *
  252. * 6 bytes ecc sector 0, *
  253. * 2 bytes sector 0 flag, *
  254. * 8 bytes unit data sector 0, *
  255. * interleave 2 *
  256. * page organization : *
  257. * 512 bytes data sector 0, *
  258. * 6 bytes ecc sector 0, *
  259. * 2 bytes sector 0 flag, *
  260. * 2 bytes sector 1 flags, *
  261. * 512 bytes data sector 1 , *
  262. * 6 bytes ecc sector 1, *
  263. * 8 bytes unit data sector 0, *
  264. * 8 bytes unit data sector 1 *
  265. * *
  266. * AUTHOR: arie tamam *
  267. * *
  268. * HISTORY: created november 14 2000 *
  269. * *
  270. *********************************************************************/
  271. /*********************************************************************/
  272. /* | Physical address of interleave - 2 page */
  273. /* Area -----------------------------------------------------*/
  274. /* | First Sector | Second Sector */
  275. /*-------------------------------------------------------------------*/
  276. /* Extra: | 512-519, 1040-1047 | 1034-1039, 520-521, 1048-1055 */
  277. /* Sector data | 0-511 | 522-1033 */
  278. /* Sector flags | 518-519 | 520-521 */
  279. /* Unit data | 1040-1047 | 1048-1055 */
  280. /* Edc | 512-517 | 1034-1039 */
  281. /*********************************************************************/
  282. /* Note: The address is given as a page offset 0-n where n is the */
  283. /* number of bytes the area has fo a sector (16 for extra , 2 for */
  284. /* sector flags, 8 for unit data and 512 for sector data). The */
  285. /* second sector address is given in a simmilar fation + 512. */
  286. /* Note: Extra area is exported in the floowing order: */
  287. /* sector data , edc , sector flags , unit data. */
  288. /*********************************************************************/
  289. /* Area A : 0 - 511 | Area B : 512 - 1023 | Area C : 1024 - 1055 */
  290. /*********************************************************************/
  291. /*********************************************************************/
  292. /* Area | Physical address of interleave - 1 page */
  293. /*-------------------------------------------------------------------*/
  294. /* Extra: | 512 - 517 , 518 - 519 , 520 - 527 */
  295. /* Sector data | 0 - 511 */
  296. /* Edc | 512 - 517 */
  297. /* Sector flags | 518 - 519 */
  298. /* Unit data | 520 - 527 */
  299. /*********************************************************************/
  300. /* Note: The address is given as a page offset 0-n where n is the */
  301. /* number of bytes the area has for a sector (16 for extra , 2 for */
  302. /* sector flags, 8 for unit data and 512 for sector data). */
  303. /* Note: Extra area is exported in the floowing order: */
  304. /* sector data , edc , sector flags , unit data. */
  305. /*********************************************************************/
  306. /* Area A : 0 - 255 | Area B : 256 - 511 | Area C : 512 - 528 */
  307. /*********************************************************************/
  308. /** include files **/
  309. #include "mdocplus.h"
  310. #include "reedsol.h"
  311. #ifdef HW_PROTECTION
  312. #include "protectp.h"
  313. #endif /* HW_PROTECTION */
  314. /* Yield CPU time in msecs */
  315. #ifndef YIELD_CPU
  316. #define YIELD_CPU 10
  317. #endif /* YIELD_CPU */
  318. /* maximum waiting time in msecs */
  319. #define MAX_WAIT 30
  320. extern NFDC21Vars docMtdVars[SOCKETS];
  321. /* When the MTD is used as a standalone package some of the routine */
  322. /* are replaced with the following macroes */
  323. #ifdef MTD_STANDALONE
  324. #define flReadBackBufferOf(a) &(globalReadBack[a][0])
  325. #define flSocketNoOf(socket) 0 /* currently we support only a single device */
  326. #define flMap(socket,address) addToFarPointer(socket->base, address & (socket->size - 1));
  327. #endif /* MTD_STANDALONE */
  328. #ifndef FL_NO_USE_FUNC
  329. /*----------------------------------------------------------------------*/
  330. /* c h o o s e D e f a u l t I F _ C F G */
  331. /* */
  332. /* Choose the default IF_CFG to use before is can actually be detected */
  333. /* */
  334. /* Parameters: */
  335. /* busConfig : Socket access discriptor */
  336. /* */
  337. /* Returns: */
  338. /* Suspected IF_CFG configuration (either 8 or 16). */
  339. /*----------------------------------------------------------------------*/
  340. static byte chooseDefaultIF_CFG(dword busConfig)
  341. {
  342. if(( busConfig & FL_BUS_HAS_8BIT_ACCESS )&&
  343. ((busConfig & FL_XX_ADDR_SHIFT_MASK) == FL_NO_ADDR_SHIFT) )
  344. {
  345. /* Assume if_cfg was set to 0. Interleave is irelevant */
  346. return 8;
  347. }
  348. /* Assume if_cfg was set to 1. Interleave is irelevant */
  349. return 16;
  350. }
  351. /*----------------------------------------------------------------------*/
  352. /* s e t D O C P l u s B u s T y p e */
  353. /* */
  354. /* Check validity and set the proper memory access routines for MTD. */
  355. /* */
  356. /* Parameters: */
  357. /* flash : Pointer identifying drive */
  358. /* busConfig : Socket access discriptor */
  359. /* interleave : Interleave factor (1,2) */
  360. /* if_cfg : if_cfg state: */
  361. /* 8 - 8 bit */
  362. /* 16 - 16 bit */
  363. /* */
  364. /* Returns: */
  365. /* TRUE if routines are available and fit the DiskOnChip */
  366. /* configuration otherwise FALSE. */
  367. /* */
  368. /* The variable pointer to by busConfig is added TrueFFS private */
  369. /* MTD descriptors. */
  370. /*----------------------------------------------------------------------*/
  371. static FLBoolean setDOCPlusBusType(FLFlash * flash,
  372. dword busConfig,
  373. byte interleave,
  374. byte if_cfg)
  375. {
  376. switch(interleave)
  377. {
  378. case 1: /* No interleave */
  379. busConfig |= FL_8BIT_FLASH_ACCESS;
  380. break;
  381. case 2: /* 2 flashes are interleaved */
  382. busConfig |= FL_16BIT_FLASH_ACCESS;
  383. break;
  384. default:
  385. DEBUG_PRINT(("ERROR: No such interleave factor (setDOCPlusBusType).\r\n"));
  386. return FALSE;
  387. }
  388. switch(if_cfg)
  389. {
  390. case 8: /* No interleave */
  391. busConfig |= FL_8BIT_DOC_ACCESS;
  392. break;
  393. case 16: /* 2 flashes are interleaved */
  394. busConfig |= FL_16BIT_DOC_ACCESS;
  395. break;
  396. default:
  397. DEBUG_PRINT(("ERROR: Invalid if_cfg value (setDOCPlusBusType).\r\n"));
  398. return FALSE;
  399. }
  400. if(setBusTypeOfFlash(flash, busConfig) != flOK)
  401. return FALSE;
  402. return TRUE;
  403. }
  404. #endif /* FL_NO_USE_FUNC */
  405. #ifndef NO_EDC_MODE
  406. /*���������������������������.*/
  407. /* EDC control */
  408. /*���������������������������.*/
  409. /*----------------------------------------------------------------------*/
  410. /* e c c E r r o r */
  411. /* */
  412. /* Check for EDC error. */
  413. /* */
  414. /* Parameters: */
  415. /* flash : Pointer identifying drive */
  416. /* */
  417. /* Returns TRUE if an EDC detected an error, otherwise FALSE. */
  418. /*----------------------------------------------------------------------*/
  419. static FLBoolean eccError (FLFlash * flash)
  420. {
  421. register int i;
  422. for(i=0;( i < 2 ); i++)
  423. flWrite8bitRegPlus(flash,NNOPreg, 0);
  424. return ((FLBoolean)flRead8bitRegPlus(flash,NECCcontrol) & ECC_CNTRL_ERROR_MASK);
  425. }
  426. /*----------------------------------------------------------------------*/
  427. /* e c c O F F */
  428. /* */
  429. /* Disable ECC. */
  430. /* */
  431. /* Parameters: */
  432. /* flash : Pointer identifying drive */
  433. /* */
  434. /*----------------------------------------------------------------------*/
  435. #define eccOFF(vol) flWrite8bitRegPlus(vol,NECCcontrol,ECC_CNTRL_IGNORE_MASK)
  436. /*----------------------------------------------------------------------*/
  437. /* e c c O N r e a d */
  438. /* */
  439. /* Enable ECC in read mode and reset it. */
  440. /* */
  441. /* Parameters: */
  442. /* flash : Pointer identifying drive */
  443. /* */
  444. /*----------------------------------------------------------------------*/
  445. #define eccONread(flash) flWrite8bitRegPlus(flash,NECCcontrol,ECC_RESET); flWrite8bitRegPlus(flash,NECCcontrol,ECC_CNTRL_ECC_EN_MASK)
  446. #ifndef FL_READ_ONLY
  447. /*----------------------------------------------------------------------*/
  448. /* e c c O n w r i t e */
  449. /* */
  450. /* Enable ECC in write mode and reset it. */
  451. /* */
  452. /* Parameters: */
  453. /* flash : Pointer identifying drive */
  454. /* */
  455. /*----------------------------------------------------------------------*/
  456. #define eccONwrite(flash) flWrite8bitRegPlus(flash,NECCcontrol,ECC_RESET); flWrite8bitRegPlus(flash,NECCcontrol,ECC_CNTRL_ECC_RW_MASK | ECC_CNTRL_ECC_EN_MASK);
  457. #endif /* FL_READ_ONLY */
  458. #endif /* NO_EDC_MODE */
  459. /*������������������������*/
  460. /* Auxiliary methods */
  461. /*������������������������*/
  462. /*----------------------------------------------------------------------*/
  463. /* s e l e c t C h i p */
  464. /* */
  465. /* Write to deviceSelector register. */
  466. /* */
  467. /* Parameters: */
  468. /* flash : Pointer identifying drive */
  469. /* wp : FLS_SEL_WP_MASK to write protect the flashes 0 to */
  470. /* remove write protection. */
  471. /* dev : Chip to select.(not used in mdocp). */
  472. /* */
  473. /* NOTE: write protection signal is common for all of the flash devices.*/
  474. /*----------------------------------------------------------------------*/
  475. #define selectChip(flash, writeProtect) flWrite8bitRegPlus(flash,NflashSelect, writeProtect)
  476. /*----------------------------------------------------------------------*/
  477. /* c h k I n t e r l e v e */
  478. /* */
  479. /* Check the current intelreave mode. */
  480. /* */
  481. /* Parameters: */
  482. /* flash : Pointer identifying drive */
  483. /* */
  484. /* Returns: Returns 1 for interleave-1 or 2 interleave-2. */
  485. /*----------------------------------------------------------------------*/
  486. #define chkInterleave(flash) (byte)(((flRead8bitRegPlus(flash,NconfigInput) & CONFIG_INTLV_MASK) == CONFIG_INTLV_MASK) ? 2 : 1)
  487. /*----------------------------------------------------------------------*/
  488. /* c h k I F _ C F G */
  489. /* */
  490. /* Check the current if_cfg mode (number of active DiskOnChip data bits */
  491. /* */
  492. /* Parameters: */
  493. /* flash : Pointer identifying drive */
  494. /* */
  495. /* Returns: Either 8 or 16. */
  496. /*----------------------------------------------------------------------*/
  497. #define chkIF_CFG(flash) (byte)((flRead8bitRegPlus(flash,NconfigInput) & CONFIG_IF_CFG_MASK) ? 16 : 8)
  498. /*----------------------------------------------------------------------*/
  499. /* s e t I p l S i z e */
  500. /* */
  501. /* Open the extended IPL of cascaded DiskOnChip and return previous */
  502. /* max ID number. */
  503. /* */
  504. /* Note floor 0 resides of offset 0 */
  505. /* floor 1 resides of offset 0x400 */
  506. /* floor 2 resides of offset 0x1800 */
  507. /* floor 3 resides of offset 0x1c00 */
  508. /* */
  509. /* Parameters: */
  510. /* flash : Pointer identifying drive */
  511. /* noOfFloors : Number of floors to open */
  512. /* */
  513. /* */
  514. /* Returns: The previous max ID number. */
  515. /*----------------------------------------------------------------------*/
  516. static byte setIplSize(FLFlash * flash, byte noOfFloors)
  517. {
  518. byte prevMaxId = flRead8bitRegPlus(flash,NconfigInput);
  519. flWrite8bitRegPlus(flash,NconfigInput,(byte)((prevMaxId & (~CONFIG_MAX_ID_MASK))|((noOfFloors-1)<<4)));
  520. return (prevMaxId & CONFIG_MAX_ID_MASK);
  521. }
  522. /*----------------------------------------------------------------------*/
  523. /* g e t C o n t r o l l e r I D */
  524. /* */
  525. /* Get the controller (ASIC) indetification byte from offset 0x1000. */
  526. /* */
  527. /* Parameters: */
  528. /* flash : Pointer identifying drive */
  529. /* */
  530. /* Returns: One of the following values. */
  531. /* CHIP_ID_MDOCP - 0x40 - DiskOnChip Millennium Plus 32MB */
  532. /* CHIP_ID_MDOCP - 0x41 - DiskOnChip Millennium Plus 16MB */
  533. /* other - Unknown DiskOnChip */
  534. /*----------------------------------------------------------------------*/
  535. #define getControllerID(flash) flRead8bitRegPlus(flash,NchipId)
  536. /*----------------------------------------------------------------------*/
  537. /* b u s y */
  538. /* */
  539. /* Pole the selected flash busy signal. */
  540. /* */
  541. /* Parameters: */
  542. /* flash : Pointer identifying drive */
  543. /* */
  544. /* Returns TRUE if the flash is busy, otherwise FALSE. */
  545. /*----------------------------------------------------------------------*/
  546. #define busy(flash) (((flRead8bitRegPlus(flash,NflashControl) & (Reg8bitType)FLS_FR_B_MASK) == FLS_FR_B_MASK) ? FALSE:TRUE)
  547. /*----------------------------------------------------------------------*/
  548. /* w a i t F o r R e a d y */
  549. /* */
  550. /* Wait until flash device is ready or timeout. */
  551. /* */
  552. /* Parameters: */
  553. /* flash : Pointer identifying drive */
  554. /* Returns: */
  555. /* FALSE if timeout error, otherwise TRUE. */
  556. /* */
  557. /*----------------------------------------------------------------------*/
  558. static FLBoolean waitForReady (FLFlash * flash)
  559. {
  560. volatile Reg8bitType junk = 0;
  561. int i;
  562. /* before polling for BUSY status perform 4 read operations from
  563. NNOPreg */
  564. for(i=0;( i < 4 ); i++ )
  565. junk += flRead8bitRegPlus(flash,NNOPreg);
  566. for(i=0;( i < BUSY_DELAY ); i++)
  567. {
  568. if( busy(flash) )
  569. {
  570. continue; /* it's not ready */
  571. }
  572. return( TRUE ); /* ready at last.. */
  573. }
  574. DEBUG_PRINT(("Debug: timeout error in waitForReady routine.\r\n"));
  575. /* Restore write proection to reduce power consumption */
  576. selectChip(flash,MPLUS_SEL_WP);
  577. return( FALSE );
  578. }
  579. #ifndef MTD_STANDALONE
  580. #ifndef DO_NOT_YIELD_CPU
  581. /*----------------------------------------------------------------------*/
  582. /* w a i t F o r R e a d y W i t h Y i e l d C P U */
  583. /* */
  584. /* Wait until flash device is ready or timeout. */
  585. /* The function yields CPU while it waits till flash is ready */
  586. /* */
  587. /* Parameters: */
  588. /* flash : Pointer identifying drive */
  589. /* */
  590. /* Returns: */
  591. /* FALSE if timeout error, otherwise TRUE. */
  592. /*----------------------------------------------------------------------*/
  593. static FLBoolean waitForReadyWithYieldCPU (FLFlash * flash, word millisecToSleep)
  594. {
  595. int i;
  596. for (i=0; i < (millisecToSleep / YIELD_CPU); i++)
  597. {
  598. #ifndef NT5PORT
  599. flsleep(YIELD_CPU);
  600. #endif /*NT5PORT*/
  601. if( busy(flash) )
  602. continue;
  603. return( TRUE ); /* ready at last.. */
  604. }
  605. return( FALSE );
  606. }
  607. #endif /* DO_NOT_YIELD_CPU */
  608. #endif /* MTD_STANDALONE */
  609. /*----------------------------------------------------------------------*/
  610. /* s e l e c t F l o o r */
  611. /* */
  612. /* Change the floor according to the given address. */
  613. /* */
  614. /* Parameters: */
  615. /* flash : Pointer identifying drive */
  616. /* address : Address of the new floor */
  617. /* */
  618. /* Note - global variable NFDC21thisVars->currentFloor is updated */
  619. /*----------------------------------------------------------------------*/
  620. static void selectFloor (FLFlash * flash, CardAddress address)
  621. {
  622. if( flash->noOfFloors > 1 )
  623. {
  624. NFDC21thisVars->currentFloor = (byte)(address >> NFDC21thisVars->floorSizeBits);
  625. setFloor(flash,NFDC21thisVars->currentFloor); /* select ASIC */
  626. }
  627. }
  628. /*----------------------------------------------------------------------*/
  629. /* r e l e a s e P o w e r D o w n */
  630. /* */
  631. /* Release the controller (ASIC) from power down mode. */
  632. /* */
  633. /* Parameters: */
  634. /* flash : Pointer identifying drive */
  635. /* */
  636. /* Note - While in power down the registers can not be read or written */
  637. /* to. */
  638. /*----------------------------------------------------------------------*/
  639. void releasePowerDown(FLFlash * flash)
  640. {
  641. int i;
  642. volatile Reg8bitType junk = 0;
  643. /* perform 3 reads + 1 from 0x1fff */
  644. for(i = 0;( i < 4 ); i++ )
  645. junk += flRead8bitRegPlus(flash,NreleasePowerDown);
  646. }
  647. /*----------------------------------------------------------------------*/
  648. /* i s A c c e s s E r r o r */
  649. /* */
  650. /* Check if protection violation had accured. */
  651. /* */
  652. /* Parameters: */
  653. /* flash : Pointer identifying drive */
  654. /* */
  655. /* Note - While in protection violation state, the registers can not be */
  656. /* read or written to. */
  657. /* */
  658. /* Returns: TRUE on protection violation, otherwise FALSE. */
  659. /*----------------------------------------------------------------------*/
  660. #define isAccessError(flash) ((flRead8bitRegPlus(flash,NprotectionStatus) & PROTECT_STAT_ACCERR) ? TRUE:FALSE)
  661. /*----------------------------------------------------------------------*/
  662. /* r e c o v e r A c c e s s E r r o r */
  663. /* */
  664. /* Recover from protection violation. */
  665. /* */
  666. /* Note : DiskOnChip must already be in Normal mode. */
  667. /* */
  668. /* Parameters: */
  669. /* flash : Pointer identifying drive */
  670. /* */
  671. /* Note : If the device was indeed in access error the routine will */
  672. /* force the device into reset mode. */
  673. /* */
  674. /* Returns: flOK on success, otherwise flHWProtection. */
  675. /*----------------------------------------------------------------------*/
  676. static FLStatus recoverFromAccessError(FLFlash * flash)
  677. {
  678. int i = 0;
  679. /* Check if there realy is an access error if not return */
  680. if(isAccessError(flash)==FALSE)
  681. return flOK;
  682. /* Folloing is the sequance to remove the protection violation */
  683. /* Write 0xff to the flash command register */
  684. /* Write twice to the write pipeline termination register */
  685. /* Write once to the NOop register */
  686. flWrite8bitRegPlus(flash,NflashCommand,(Reg8bitType)RESET_FLASH);
  687. for(i = 0; i< 2; i++)
  688. flWrite8bitRegPlus(flash,NwritePipeTerm,(Reg8bitType)0);
  689. flWrite8bitRegPlus(flash,NNOPreg,(Reg8bitType)0);
  690. /* Check if access error was removed */
  691. if (flRead8bitRegPlus(flash,NprotectionStatus) & PROTECT_STAT_ACCERR)
  692. {
  693. DEBUG_PRINT(("Can't recover from protection violation\r\n"));
  694. return flHWProtection;
  695. }
  696. return flOK;
  697. }
  698. /*----------------------------------------------------------------------*/
  699. /* s e t A S I C m o d e */
  700. /* */
  701. /* Set the controller (ASIC) operation mode. */
  702. /* */
  703. /* Parameters: */
  704. /* flash : Pointer identifying drive */
  705. /* mode : One of the modes below: */
  706. /* DOC_CNTRL_MODE_RESET - Reset mode */
  707. /* DOC_CNTRL_MODE_NORMAL - Normal mode */
  708. /* DOC_CNTRL_MODE_PWR_DWN - Power down mode */
  709. /* */
  710. /* Note: The mode is common to all cascaded floors. */
  711. /* */
  712. /* Returns: flOK on success, otherwise flHWProtection. */
  713. /*----------------------------------------------------------------------*/
  714. static FLStatus setASICmode (FLFlash * flash, Reg8bitType mode)
  715. {
  716. volatile Reg8bitType stat = 0;
  717. /* Get out of power down mode - just in case */
  718. releasePowerDown(flash);
  719. /* Set ASIC state
  720. * Use default bit values to all bits but the last 2 mode bits
  721. * ORed with the given mode. The mode is written to the the
  722. * NDOCcontrol register and its complement to the
  723. * NDOCcontrolConfirm register
  724. */
  725. stat = DOC_CNTRL_DEFAULT | mode;
  726. flWrite8bitRegPlus(flash,NDOCcontrol,stat); /* the control data */
  727. flWrite8bitRegPlus(flash,NDOCcontrolConfirm, (Reg8bitType)~stat); /* confirm */
  728. if (mode & DOC_CNTRL_MODE_PWR_DWN)
  729. return flOK;
  730. /* Read Controller's (ASIC) modes register */
  731. stat = flRead8bitRegPlus(flash,NDOCcontrol);
  732. /* Check for power down mode */
  733. if (stat & DOC_CNTRL_MODE_NORMAL)
  734. {
  735. /* Check for protection violation */
  736. return recoverFromAccessError(flash);
  737. }
  738. return flOK;
  739. }
  740. /*----------------------------------------------------------------------*/
  741. /* c h k A S I C m o d e */
  742. /* */
  743. /* Check the controller (ASIC) mode and change it to normal. */
  744. /* */
  745. /* Parameters: */
  746. /* flash : Pointer identifying drive */
  747. /* */
  748. /* Note: The mode is common to all cascaded floors. */
  749. /* Note: This routine is called by each of the MTD exported routine. */
  750. /* */
  751. /* Returns: flOK on success, otherwise flHWProtection. */
  752. /*----------------------------------------------------------------------*/
  753. FLStatus chkASICmode (FLFlash * flash)
  754. {
  755. volatile Reg8bitType stat;
  756. FLStatus status = flOK;
  757. stat = flRead8bitRegPlus(flash,NDOCcontrol);
  758. if ((isAccessError(flash) == TRUE) || /* Protection violation */
  759. (!(stat & DOC_CNTRL_MODE_NORMAL))) /* already in normal mode */
  760. {
  761. status = setASICmode(flash,DOC_CNTRL_MODE_NORMAL);
  762. setFloor (flash, NFDC21thisVars->currentFloor);
  763. }
  764. return status;
  765. }
  766. /*----------------------------------------------------------------------*/
  767. /* c h k I P L D o w n l o a d */
  768. /* */
  769. /* Check if IPL was downloaded without an IPL dwonload error. */
  770. /* */
  771. /* Parameters: */
  772. /* flash : Pointer identifying drive */
  773. /* */
  774. /* Returns: TRUE if download was succesfull on both copies. */
  775. /*----------------------------------------------------------------------*/
  776. #define chkIPLDownload(flash) ((flRead8bitRegPlus(flash, NdownloadStatus) & (DWN_STAT_IPL0 | DWN_STAT_IPL1)) ? FALSE : TRUE)
  777. /*----------------------------------------------------------------------*/
  778. /* c h k A S I C D o w n l o a d */
  779. /* */
  780. /* Check if DPS and OTP were downloaded without any error from the */
  781. /* specified floor. */
  782. /* */
  783. /* Parameters: */
  784. /* flash : Pointer identifying drive */
  785. /* floor : The floor to check */
  786. /* */
  787. /* Note - The routine changes the controller (ASIC) mode to normal. */
  788. /* */
  789. /* Returns: */
  790. /* FLStatus : 0 on success, flBadDownload on download error */
  791. /* and flHWProtection if controller mode could */
  792. /* not be changed. */
  793. /*----------------------------------------------------------------------*/
  794. static FLStatus chkASICDownload (FLFlash * flash,byte floorNo)
  795. {
  796. FLStatus status;
  797. status = setASICmode(flash, DOC_CNTRL_MODE_NORMAL);
  798. if(status != flOK)
  799. return status;
  800. setFloor(flash,floorNo);
  801. if(flRead8bitRegPlus(flash,NdownloadStatus) & DWN_STAT_DWLD_ERR)
  802. return flBadDownload;
  803. return flOK;
  804. }
  805. /*----------------------------------------------------------------------*/
  806. /* p o w e r D o w n */
  807. /* */
  808. /* Change the device mode to minimal power consumption (but not active) */
  809. /* and back to normal mode. */
  810. /* */
  811. /* Parameters: */
  812. /* flash : Pointer identifying drive */
  813. /* state : DEEP_POWER_DOWN flag for entering power down */
  814. /* otherwise return to normal mode. */
  815. /* */
  816. /* Returns: */
  817. /* FLStatus : 0 on success, otherwise fail. */
  818. /*----------------------------------------------------------------------*/
  819. static FLStatus powerDown(FLFlash * flash, word state)
  820. {
  821. if (state & DEEP_POWER_DOWN)
  822. {
  823. return setASICmode (flash, DOC_CNTRL_MODE_PWR_DWN);
  824. }
  825. else
  826. {
  827. return chkASICmode (flash);
  828. }
  829. }
  830. #if (defined(HW_PROTECTION) || !defined(NO_IPL_CODE) || defined (HW_OTP))
  831. /*----------------------------------------------------------------------*/
  832. /* f o r c e D o w n l o a d */
  833. /* */
  834. /* Force download of protection mechanism and IPL code. */
  835. /* */
  836. /* Parameters: */
  837. /* flash : Pointer identifying drive */
  838. /* */
  839. /* Note - The routine changes the controller (ASIC) mode to normal. */
  840. /* */
  841. /* Returns: */
  842. /* FLStatus : 0 on success, flBadDownload on download error */
  843. /* and flHWProtection if controller mode could */
  844. /* not be changed. */
  845. /*----------------------------------------------------------------------*/
  846. static FLStatus forceDownLoad(FLFlash * flash)
  847. {
  848. volatile Reg8bitType val;
  849. register byte i;
  850. dword counter = 0;
  851. FLStatus status;
  852. /* Prevent assertion of the BUSY# signal */
  853. for(i=0;i<flash->noOfFloors;i++)
  854. {
  855. /* Select floor */
  856. setFloor(flash,i);
  857. /* Remove last bit */
  858. val = flRead8bitRegPlus(flash, NoutputControl) & OUT_CNTRL_BSY_DISABLE_MASK;
  859. flWrite8bitRegPlus(flash, NoutputControl, val);
  860. }
  861. /* Force download */
  862. flWrite8bitRegPlus(flash, NfoudaryTest, FOUNDRY_WRITE_ENABLE);
  863. flWrite8bitRegPlus(flash, NfoudaryTest, FOUNDRY_DNLD_MASK);
  864. flDelayMsecs(100);
  865. /* Check that the download is really over. The Device does not
  866. respond while in download state therfore we try to write and
  867. read to a harmless register 10 times assuming if all 10 times
  868. are good then the download is over */
  869. do
  870. {
  871. /* Set device to normal mode */
  872. flWrite8bitRegPlus(flash,NDOCcontrol,DOC_CNTRL_DEFAULT | DOC_CNTRL_MODE_NORMAL);
  873. flWrite8bitRegPlus(flash,NDOCcontrolConfirm,(byte)(~(DOC_CNTRL_DEFAULT | DOC_CNTRL_MODE_NORMAL)));
  874. for (i=0; i<10; i++,counter++) /* must get expecetd result 10 times in a row */
  875. {
  876. val = (i & 1 ? 0x55 : 0xAA) + i; /* generate various data for the test pattern */
  877. flWrite8bitRegPlus(flash,NaliasResolution,(byte)val); /* write the test data */
  878. flWrite8bitRegPlus(flash,NNOPreg,(byte)~val); /* put the complement on the data bus */
  879. if (flRead8bitRegPlus(flash,NaliasResolution) != (byte)val) /* verify test data */
  880. break; /* still downloading so start over */
  881. }
  882. } while ((i < 10) && (counter < DOWNLOAD_BUSY_DELAY)); /* i==10 only when download has completed */
  883. /* Check for download errors on all floors */
  884. for (i=0;i<flash->noOfFloors;i++)
  885. {
  886. status = chkASICDownload(flash,i);
  887. if(status != flOK)
  888. return status;
  889. }
  890. return flOK;
  891. }
  892. #endif /* HW_PROTECTION or !NO_IPL_CODE or HW_OTP */
  893. /*----------------------------------------------------------------------*/
  894. /* c h e c k T o g g l e */
  895. /* */
  896. /* Read the toggle bit twice making sure it toggles. */
  897. /* */
  898. /* Note : This routine assumes that the memory access routines have */
  899. /* already been initialized by the called routine. */
  900. /* */
  901. /* Parameters: */
  902. /* FLFlash : Pointer to flash structure. */
  903. /* */
  904. /* Returns: */
  905. /* FLStatus: TRUE if the bit toggles verifing that this is indeed */
  906. /* a DiskOnChip device, otherwise FALSE. */
  907. /*----------------------------------------------------------------------*/
  908. static FLBoolean checkToggle(FLFlash * flash)
  909. {
  910. volatile Reg8bitType toggle1;
  911. volatile Reg8bitType toggle2;
  912. toggle1 = flRead8bitRegPlus(flash,NECCcontrol);
  913. toggle2 = toggle1 ^ flRead8bitRegPlus(flash,NECCcontrol);
  914. if( (toggle2 & ECC_CNTRL_TOGGLE_MASK) == 0 )
  915. {
  916. return FALSE;
  917. }
  918. return TRUE;
  919. }
  920. #ifndef MTD_STANDALONE
  921. /*----------------------------------------------------------------------*/
  922. /* c h e c k W i n F o r D O C P L U S */
  923. /* */
  924. /* Send commands to release MDOCP from power down, reset it and set it */
  925. /* normal mode. Then make sure this is an MDOCP by reading chip ID and */
  926. /* check the toggle bit. */
  927. /* */
  928. /* Parameters: */
  929. /* socketNo : Device number */
  930. /* memWinPtr : Pointer to DiskOnChip window */
  931. /* */
  932. /* Returns: TRUE if this is an MDOCP, otherwise FALSE. */
  933. /*----------------------------------------------------------------------*/
  934. FLBoolean checkWinForDOCPLUS(unsigned socketNo, NDOC2window memWinPtr)
  935. {
  936. register int i;
  937. volatile Reg8bitType junk = 0;
  938. Reg8bitType prevNDOCcontrol, prevNDOCcontrolConfirm;
  939. FLFlash * flash = flFlashOf(socketNo);
  940. /* Initialize socket memory access routine */
  941. flash->win = memWinPtr;
  942. #ifndef FL_NO_USE_FUNC
  943. if(setDOCPlusBusType(flash, flBusConfig[socketNo] , 1,
  944. chooseDefaultIF_CFG(flBusConfig[socketNo])) == FALSE)
  945. return FALSE;
  946. #endif /* FL_NO_USE_FUNC */
  947. /* release from Power Down Mode */
  948. /* perform 3 reads from anywhere + 1 from 0x1fff */
  949. for(i = 0;( i < 4 ); i++ )
  950. junk += flRead8bitRegPlus(flash,NreleasePowerDown);
  951. /* Save memory data before writting it */
  952. prevNDOCcontrol = flRead8bitRegPlus(flash,NDOCcontrol);
  953. prevNDOCcontrolConfirm = flRead8bitRegPlus(flash,NDOCcontrolConfirm);
  954. /* set ASIC to RESET MODE */
  955. junk = DOC_CNTRL_DEFAULT | DOC_CNTRL_MODE_RESET;
  956. flWrite8bitRegPlus(flash,NDOCcontrol,junk); /* the control data */
  957. flWrite8bitRegPlus(flash,NDOCcontrolConfirm,(Reg8bitType)~junk); /* confirm */
  958. /* set ASIC to NORMAL MODE */
  959. junk |= DOC_CNTRL_MODE_NORMAL; /* write normal mode */
  960. flWrite8bitRegPlus(flash,NDOCcontrol,junk); /* the control data */
  961. flWrite8bitRegPlus(flash,NDOCcontrolConfirm,(Reg8bitType)~junk); /* confirm */
  962. /* check if it's MDOCP ID + check the toggle bit */
  963. junk = getControllerID(flash);
  964. if((junk == CHIP_ID_MDOCP) || (junk == CHIP_ID_MDOCP16))
  965. {
  966. #ifndef FL_NO_USE_FUNC
  967. /* Check if_cfg before checking toggle bit */
  968. if(setDOCPlusBusType(flash,flBusConfig[socketNo],1,chkIF_CFG(flash)) == FALSE)
  969. {
  970. setDOCPlusBusType(flash,flBusConfig[socketNo],1,
  971. chooseDefaultIF_CFG(flBusConfig[socketNo]));
  972. }
  973. else
  974. #endif /* FL_NO_USE_FUNC */
  975. {
  976. if(checkToggle(flash))
  977. return TRUE;
  978. }
  979. }
  980. /* If this is not a MDOCP return the previous values */
  981. flWrite8bitRegPlus(flash,NDOCcontrol,prevNDOCcontrol);
  982. flWrite8bitRegPlus(flash,NDOCcontrolConfirm,prevNDOCcontrolConfirm);
  983. return FALSE;
  984. }
  985. #endif /* MTD_STANDALONE */
  986. /*----------------------------------------------------------------------*/
  987. /* f l D o c W i n d o w B a s e A d d r e s s */
  988. /* */
  989. /* Return the host base address of the window. */
  990. /* If the window base address is programmable, this routine selects */
  991. /* where the base address will be programmed to. */
  992. /* */
  993. /* Parameters: */
  994. /* socketNo : FLite socket No (0..SOCKETS-1) */
  995. /* lowAddress, */
  996. /* highAddress : host memory range to search for DiskOnChip Plus */
  997. /* memory window */
  998. /* */
  999. /* Returns: */
  1000. /* Host physical address of window divided by 4 KB */
  1001. /* nextAddress : The address of the next DiskOnChip. */
  1002. /*----------------------------------------------------------------------*/
  1003. static unsigned flDocWindowBaseAddress(byte socketNo, dword lowAddress,
  1004. dword highAddress, dword *nextAddress)
  1005. {
  1006. #ifndef NT5PORT
  1007. dword winSize;
  1008. FLFlash *flash;
  1009. FLBoolean stopSearch = FALSE;
  1010. volatile Reg8bitType junk = 0;
  1011. /* if memory range to search for DiskOnChip window is not specified */
  1012. /* assume the standard x86 PC architecture where DiskOnChip Plus appears */
  1013. /* in a memory range reserved for BIOS expansions */
  1014. if (lowAddress == 0x0L)
  1015. {
  1016. lowAddress = START_ADR;
  1017. highAddress = STOP_ADR;
  1018. }
  1019. /* Initialize socket memory access routine */
  1020. flash = flFlashOf(socketNo);
  1021. #ifndef FL_NO_USE_FUNC
  1022. if(setDOCPlusBusType(flash, flBusConfig[socketNo], 1,
  1023. chooseDefaultIF_CFG(flBusConfig[socketNo])) == FALSE)
  1024. return ( 0 );
  1025. #endif /* FL_NO_USE_FUNC */
  1026. winSize = DOC_WIN;
  1027. /* set all possible controllers (ASIC) to RESET MODE */
  1028. for(*nextAddress = lowAddress; *nextAddress <= highAddress;
  1029. *nextAddress += winSize)
  1030. {
  1031. flash->win = (NDOC2window)physicalToPointer(*nextAddress,winSize,socketNo);
  1032. junk = DOC_CNTRL_DEFAULT | DOC_CNTRL_MODE_RESET;
  1033. flWrite8bitRegPlus(flash,NDOCcontrol,junk); /* the control data */
  1034. flWrite8bitRegPlus(flash,NDOCcontrolConfirm,(Reg8bitType)~junk); /* confirm */
  1035. }
  1036. /* current address initialization */
  1037. for(*nextAddress = lowAddress ; *nextAddress <= highAddress ;
  1038. *nextAddress += winSize)
  1039. {
  1040. flash->win = (NDOC2window)physicalToPointer(*nextAddress,winSize,socketNo);
  1041. /* set controller (ASIC) to NORMAL MODE */
  1042. junk = DOC_CNTRL_DEFAULT | DOC_CNTRL_MODE_NORMAL; /* write normal mode */
  1043. flWrite8bitRegPlus(flash,NDOCcontrol,junk); /* the control data */
  1044. flWrite8bitRegPlus(flash,NDOCcontrolConfirm,(Reg8bitType)~junk); /* confirm */
  1045. junk = getControllerID(flash);
  1046. if((junk != CHIP_ID_MDOCP) && (junk != CHIP_ID_MDOCP16))
  1047. {
  1048. if( stopSearch == TRUE ) /* DiskOnChip was found */
  1049. break;
  1050. else
  1051. continue;
  1052. }
  1053. if( stopSearch == FALSE )
  1054. {
  1055. /* detect card - identify bit toggles on consequitive reads */
  1056. #ifndef FL_NO_USE_FUNC
  1057. /* Check if_cfg before checking toggle bit */
  1058. if(setDOCPlusBusType(flash,flBusConfig[socketNo],1,chkIF_CFG(flash)) == FALSE)
  1059. {
  1060. setDOCPlusBusType(flash,flBusConfig[socketNo], 1,
  1061. chooseDefaultIF_CFG(flBusConfig[socketNo]));
  1062. continue;
  1063. }
  1064. #endif /* FL_NO_USE_FUNC */
  1065. if(checkToggle(flash) == FALSE)
  1066. continue;
  1067. /* DiskOnChip found, mark alias resolution register */
  1068. flWrite8bitRegPlus(flash,NaliasResolution,(Reg8bitType)ALIAS_RESOLUTION);
  1069. stopSearch = TRUE;
  1070. lowAddress = *nextAddress; /* save DiskOnChip address */
  1071. }
  1072. else /* DiskOnChip found, continue to skip aliases */
  1073. {
  1074. /* skip Aliases that have the mark */
  1075. if(flRead8bitRegPlus(flash,NaliasResolution) != ALIAS_RESOLUTION)
  1076. break;
  1077. }
  1078. }
  1079. if( stopSearch == FALSE ) /* DiskOnChip memory window not found */
  1080. return( 0 );
  1081. return((unsigned)(lowAddress >> 12));
  1082. #else /*NT5PORT*/
  1083. DEBUG_PRINT(("Tffsport mdocplus.c :flDocWindowBaseAddress(): Before returning baseAddress()\n"));
  1084. return (unsigned)(((ULONG_PTR)pdriveInfo[socketNo].winBase)>> 12);
  1085. #endif /*NT5PORT*/
  1086. }
  1087. /*----------------------------------------------------------------------*/
  1088. /* s e t A d d r e s s */
  1089. /* */
  1090. /* Latch address to selected flash device. */
  1091. /* */
  1092. /* Parameters: */
  1093. /* flash : Pointer identifying drive */
  1094. /* address : byte address to latch. */
  1095. /* */
  1096. /*----------------------------------------------------------------------*/
  1097. static FLStatus setAddress (FLFlash * flash, CardAddress address)
  1098. {
  1099. /*
  1100. * bits 0..7 stays as are
  1101. * bit 8 is thrown away from address
  1102. * bits 31..9 -> bits 30..8
  1103. */
  1104. address &= NFDC21thisVars->floorSizeMask; /* Convert to floor offset */
  1105. address = address >> (flash->interleaving-1); /* Convert to interleaved address */
  1106. address = ((address >> 9) << 8) | ((byte)address); /* Remove bit 8 */
  1107. /* Send 3 bytes addres */
  1108. flWrite8bitRegPlus(flash,NflashAddress,(byte)address);
  1109. flWrite8bitRegPlus(flash,NflashAddress,(byte)(address >> 8));
  1110. flWrite8bitRegPlus(flash,NflashAddress,(byte)(address >> 16));
  1111. /* write twice to pipeline termination register */
  1112. flWrite8bitRegPlus(flash,NwritePipeTerm,(Reg8bitType)0);
  1113. flWrite8bitRegPlus(flash,NwritePipeTerm,(Reg8bitType)0);
  1114. if (waitForReady(flash)==FALSE) /* wait for ready */
  1115. return flTimedOut;
  1116. if (isAccessError(flash) == TRUE) /* Protection violation */
  1117. {
  1118. /* Restore write proection to reduce power consumption */
  1119. selectChip(flash,MPLUS_SEL_WP);
  1120. return flHWProtection;
  1121. }
  1122. return flOK;
  1123. }
  1124. /*----------------------------------------------------------------------*/
  1125. /* c o m m a n d */
  1126. /* */
  1127. /* Latch command byte to selected flash device. */
  1128. /* */
  1129. /* Parameters: */
  1130. /* flash : Pointer identifying drive */
  1131. /* code : Command to set. */
  1132. /* */
  1133. /*----------------------------------------------------------------------*/
  1134. static void command(FLFlash * flash, Reg8bitType flCode)
  1135. {
  1136. /* write the command to the flash */
  1137. flWrite8bitRegPlus(flash,NflashCommand,flCode);
  1138. /* write twice to pipline termination register */
  1139. flWrite8bitRegPlus(flash,NwritePipeTerm,flCode);
  1140. flWrite8bitRegPlus(flash,NwritePipeTerm,flCode);
  1141. }
  1142. /*----------------------------------------------------------------------*/
  1143. /* r d B u f */
  1144. /* */
  1145. /* Auxiliary routine for reading from flash I\O registers. */
  1146. /* It can be data,status or flash ID. */
  1147. /* */
  1148. /* Note - The read procedure is devided into 3 parts: */
  1149. /* 1) pipeline initialization. */
  1150. /* 2) read data from aliased I\O registers. */
  1151. /* 3) read the last 2 bytes from the last data read register. */
  1152. /* Note - Only the last 2 bytes are read from the pipeline (not 4). */
  1153. /* */
  1154. /* Parameters: */
  1155. /* flash : Pointer identifying drive */
  1156. /* buf : Buffer to read into. */
  1157. /* howmany : Number of bytes to read. */
  1158. /* */
  1159. /*----------------------------------------------------------------------*/
  1160. static void rdBuf (FLFlash * flash, void FAR1 *buf, word howmany)
  1161. {
  1162. volatile Reg16bitType junkWord = 0;
  1163. register int i;
  1164. word length = TFFSMAX(0,(Sword)howmany-2);
  1165. switch(NFDC21thisVars->if_cfg)
  1166. {
  1167. case 16: /* Host access type is 16 bit */
  1168. switch (flash->interleaving)
  1169. {
  1170. case 1:
  1171. /* Pineline init */
  1172. for (i = 0; i < ((howmany == 1) ? 1 : 2); i++)
  1173. junkWord = flRead16bitRegPlus(flash, NreadPipeInit);
  1174. /* Read data */
  1175. if (length > 0) /* Can use only one byte (int1 operation) */
  1176. {
  1177. docPlusRead(flash->win,NFDC21thisIO,(byte FAR1 *)buf,length);
  1178. }
  1179. /* Before reading the last data perform dummy read cycles */
  1180. for (i=0; i< ((howmany > 1) ? 0 : 2 ); i++)
  1181. junkWord = flRead16bitRegPlus(flash, NreadLastData_1);
  1182. /* Read last data from last data read registers */
  1183. for (i = length ; i < howmany ; i++)
  1184. *BYTE_ADD_FAR(buf,i) = flRead8bitRegPlus(flash, NreadLastData_1);
  1185. break;
  1186. case 2:
  1187. /* Pineline init */
  1188. for (i=0; i< ((howmany < 4) ? 1 : 2); i++)
  1189. junkWord = flRead16bitRegPlus(flash, NreadPipeInit);
  1190. /* Read data */
  1191. if (length > 0)
  1192. {
  1193. docPlusRead(flash->win,NFDC21thisIO,(byte FAR1 *)buf,length);
  1194. }
  1195. /* Before reading the last data perform dummy read cycles */
  1196. for (i = 0; i < ((howmany > 3) ? 0 : 2) ; i++)
  1197. junkWord = flRead16bitRegPlus(flash, NreadLastData_1);
  1198. /* Read last data from last data read registers */
  1199. for (i = length ; i < howmany ; i += flash->interleaving)
  1200. {
  1201. junkWord = flRead16bitRegPlus(flash, NreadLastData_1);
  1202. *BYTE_ADD_FAR(buf,i) = ((byte FAR1*)(&junkWord))[0];
  1203. *BYTE_ADD_FAR(buf,i+1) = ((byte FAR1*)(&junkWord))[1];
  1204. }
  1205. }
  1206. break;
  1207. case 8: /* Host access type is 8 bit */
  1208. /* Pineline init */
  1209. for (i=0; i< ((howmany >> (flash->interleaving -1)) ==1 ?1:2); i++)
  1210. junkWord += flRead8bitRegPlus(flash, NreadPipeInit);
  1211. /* Read data */
  1212. if (length > 0)
  1213. docPlusRead(flash->win,NFDC21thisIO,(byte FAR1 *)buf,length);
  1214. /* Before reading the last data perform dummy read cycles */
  1215. for (i=0; ( i < ((howmany >> (flash->interleaving -1)) > 1 ?
  1216. 0 : ((flash->interleaving == 2) ? 4:2)));i++)
  1217. junkWord = flRead8bitRegPlus(flash, NreadLastData_1);
  1218. /* Read last data from last data read registers */
  1219. for (i=length ; i< howmany ; i++)
  1220. {
  1221. *BYTE_ADD_FAR(buf,i) = flRead8bitRegPlus(flash, NreadLastData_1);
  1222. }
  1223. break;
  1224. }
  1225. }
  1226. /*----------------------------------------------------------------------*/
  1227. /* r d B u f S */
  1228. /* */
  1229. /* Auxiliary routine for reading from flash I\O registers. */
  1230. /* This routine is the pipeline initialization of the full rdBuf func'. */
  1231. /* */
  1232. /* Parameters: */
  1233. /* flash : Pointer identifying drive */
  1234. /* howmany : Number of bytes to read. */
  1235. /* */
  1236. /*----------------------------------------------------------------------*/
  1237. static void rdBufS (FLFlash * flash, word howmany)
  1238. {
  1239. volatile Reg16bitType junkWord = 0;
  1240. register int i;
  1241. switch(NFDC21thisVars->if_cfg)
  1242. {
  1243. case 16: /* Host access type is 16 bit */
  1244. /* Pineline init */
  1245. for (i=0; i< ((howmany >> (flash->interleaving -1)) ==1 ?1:2); i++)
  1246. junkWord = flRead16bitRegPlus(flash, NreadPipeInit);
  1247. break;
  1248. case 8: /* Host access type is 8 bit */
  1249. /* Pineline init */
  1250. for (i=0; i< ((howmany >> (flash->interleaving -1)) ==1 ?1:2); i++)
  1251. junkWord += flRead8bitRegPlus(flash, NreadPipeInit);
  1252. break;
  1253. }
  1254. }
  1255. /*----------------------------------------------------------------------*/
  1256. /* r e a d C o m m a n d */
  1257. /* */
  1258. /* Issue read command. */
  1259. /* */
  1260. /* Note - The routine also checks that the controller is in normal mode */
  1261. /* , latches the address and waits for the ready signal. */
  1262. /* */
  1263. /* Parametes: */
  1264. /* flash : Pointer identifying drive */
  1265. /* cmd : Command to issue (AREA_A, AREA_B or AREA_C). */
  1266. /* addr : address to read from. */
  1267. /* */
  1268. /* Returns: flOK on success, flTimedOut or flHWProtection on failures. */
  1269. /*----------------------------------------------------------------------*/
  1270. static FLStatus readCommand (FLFlash * flash, CardAddress addr, Reg8bitType cmd)
  1271. {
  1272. FLStatus status;
  1273. selectFloor(flash,addr);
  1274. /* Check mode of ASIC and set to NORMAL.*/
  1275. status = chkASICmode(flash);
  1276. if(status != flOK)
  1277. return status;
  1278. /* Select the device and remove flash write protection */
  1279. selectChip(flash,MPLUS_SEL_CE|MPLUS_SEL_WP);
  1280. /* Move flash pointer to respective area of the page */
  1281. command (flash, cmd);
  1282. /* Latche the address */
  1283. status = setAddress (flash, addr);
  1284. if(status != flOK)
  1285. return status;
  1286. /* ALE down */
  1287. flWrite8bitRegPlus(flash,NflashControl, 0x0);
  1288. /* Write twice to NOP */
  1289. flWrite8bitRegPlus(flash,NNOPreg, 0x0);
  1290. flWrite8bitRegPlus(flash,NNOPreg, 0x0);
  1291. return flOK;
  1292. }
  1293. #ifndef FL_READ_ONLY
  1294. /*----------------------------------------------------------------------*/
  1295. /* r e a d S t a t u s */
  1296. /* */
  1297. /* Read status of selected flash device. */
  1298. /* */
  1299. /* Note - The status indicated success of write and erase operations. */
  1300. /* */
  1301. /* Parameters: */
  1302. /* flash : Pointer identifying drive */
  1303. /* */
  1304. /* Returns: TRUE for failed status, FALSE for success. */
  1305. /*----------------------------------------------------------------------*/
  1306. static FLBoolean readStatus (FLFlash * flash)
  1307. {
  1308. word status;
  1309. /* send command to read status */
  1310. command(flash,READ_STATUS);
  1311. rdBuf(flash, &status,2);
  1312. return ((status & 1) ? TRUE:FALSE);
  1313. }
  1314. /*----------------------------------------------------------------------*/
  1315. /* w r i t e C o m m a n d */
  1316. /* */
  1317. /* Issue write command. */
  1318. /* */
  1319. /* Note - The routine also checks that the controller is in normal mode */
  1320. /* , latches the address and waits for the ready signal. */
  1321. /* */
  1322. /* Parametes: */
  1323. /* flash : Pointer identifying drive */
  1324. /* cmd : Command to issue (AREA_A, AREA_B or AREA_C). */
  1325. /* addr : address to read from. */
  1326. /* */
  1327. /* Returns: flOK on success, flTimedOut or flHWProtection on failures. */
  1328. /*----------------------------------------------------------------------*/
  1329. static FLStatus writeCommand (FLFlash * flash, CardAddress addr, Reg8bitType cmd)
  1330. {
  1331. FLStatus status;
  1332. selectFloor(flash,addr);
  1333. /* Check mode of ASIC and set to NORMAL.*/
  1334. status = chkASICmode(flash);
  1335. if(status != flOK)
  1336. return status;
  1337. /* Select the device and remove flash write protection */
  1338. selectChip(flash,MPLUS_SEL_CE);
  1339. /* Prepare flash for write operation */
  1340. command (flash, RESET_FLASH); /* Reset flash */
  1341. if (waitForReady(flash)==FALSE) /* always wait after flash reset */
  1342. return flTimedOut;
  1343. /* Move flash pointer to respective area of the page */
  1344. flWrite8bitRegPlus(flash,NflashCommand, (Reg8bitType)cmd); /* page area */
  1345. command (flash,SERIAL_DATA_INPUT); /* data input stream type */
  1346. /* Latche the address */
  1347. return setAddress(flash, addr); /* set page pointer */
  1348. }
  1349. /*----------------------------------------------------------------------*/
  1350. /* w r i t e E x e c u t e */
  1351. /* */
  1352. /* Execute write. */
  1353. /* */
  1354. /* Parametes: */
  1355. /* flash : Pointer identifying drive */
  1356. /* */
  1357. /* Returns: */
  1358. /* FLStatus : 0 on success, otherwise failed. */
  1359. /*----------------------------------------------------------------------*/
  1360. static FLStatus writeExecute (FLFlash * flash)
  1361. {
  1362. /* Pipe termination to preceeding write cycle */
  1363. flWrite8bitRegPlus(flash,NwritePipeTerm,(byte)0);
  1364. flWrite8bitRegPlus(flash,NwritePipeTerm,(byte)0);
  1365. command (flash, SETUP_WRITE); /* execute page program */
  1366. if (waitForReady(flash)==FALSE) /* wait for ready signal */
  1367. return flTimedOut;
  1368. if( readStatus(flash) )
  1369. {
  1370. DEBUG_PRINT(("Debug: NFDC MDOCP write failed.\r\n"));
  1371. return( flWriteFault );
  1372. }
  1373. selectChip(flash,MPLUS_SEL_WP);
  1374. return( flOK );
  1375. }
  1376. #ifndef NO_EDC_MODE
  1377. /*----------------------------------------------------------------------*/
  1378. /* w r i t e D a t a P l u s E D C */
  1379. /* */
  1380. /* Write 512 bytes data with edc */
  1381. /* */
  1382. /* Parameters: */
  1383. /* flash : Pointer identifying drive */
  1384. /* buffer : Pointer to user buffer to write from */
  1385. /* */
  1386. /*----------------------------------------------------------------------*/
  1387. static void writeDataPlusEDC(FLFlash * flash, const byte FAR1 *buffer)
  1388. {
  1389. register int i;
  1390. static byte syndrom[SYNDROM_BYTES];
  1391. eccONwrite(flash); /* ECC ON for write */
  1392. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)buffer, SECTOR_SIZE); /* user data */
  1393. /* clock data thru pipeline prior reading ECC syndrome*/
  1394. for(i=0; i<3; i++)
  1395. flWrite8bitRegPlus(flash,NNOPreg, 0);
  1396. /* read the syndrom bits */
  1397. if (NFDC21thisVars->if_cfg == 8)
  1398. {
  1399. for(i=0; i<SYNDROM_BYTES; i++)
  1400. syndrom[i] = flRead8bitRegPlus(flash,(word)(Nsyndrom+i));
  1401. }
  1402. else
  1403. {
  1404. for(i=0; i<SYNDROM_BYTES; i+=2)
  1405. *(word *)(syndrom + i) = flRead16bitRegPlus(flash,(word)(Nsyndrom+i));
  1406. }
  1407. #ifdef D2TST
  1408. tffscpy(saveSyndromForDumping,syndrom,SYNDROM_BYTES);
  1409. #endif
  1410. eccOFF(flash); /* ECC OFF */
  1411. docPlusWrite(flash->win,NFDC21thisIO,(byte FAR1 *)syndrom,SYNDROM_BYTES);
  1412. }
  1413. #endif /* NO_EDC_MODE */
  1414. #endif /* FL_READ_ONLY */
  1415. #ifndef NO_EDC_MODE
  1416. /*----------------------------------------------------------------------*/
  1417. /* r e a d D a t a P l u s E D C */
  1418. /* */
  1419. /* Read 512 bytes data with edc */
  1420. /* */
  1421. /* Parameters: */
  1422. /* flash : Pointer identifying drive */
  1423. /* buffer : Pointer to user buffer to read into */
  1424. /* length : Length to read */
  1425. /* modes : With or without second try option */
  1426. /* address : Address to read from */
  1427. /* cmd : Area command to read from */
  1428. /* endhere : Flag indicating if more bytes are needed from */
  1429. /* this page. Importent for last byte read operation */
  1430. /* */
  1431. /* Return: flOK on success, otherwise flDataError. */
  1432. /*----------------------------------------------------------------------*/
  1433. static FLStatus readDataPlusEDC(FLFlash * flash, const byte FAR1 *buffer,
  1434. word length, word modes, CardAddress address,
  1435. byte cmd,FLBoolean endHere)
  1436. {
  1437. byte syndrom[SYNDROM_BYTES];
  1438. word unreadBytes = SECTOR_SIZE - length;
  1439. volatile word tmp;
  1440. FLStatus status;
  1441. #ifdef LOG_FILE
  1442. FILE *out;
  1443. #endif /* LOG_FILE */
  1444. /* To avoid page fault, read first and last bytes of the page */
  1445. if (length > 0)
  1446. {
  1447. ((byte FAR1 *)buffer)[0] = 0;
  1448. ((byte FAR1 *)buffer)[length-1] = 0;
  1449. }
  1450. /* activate ecc mechanism */
  1451. eccONread(flash);
  1452. /* read the sector data */
  1453. docPlusRead(flash->win,NFDC21thisIO, (byte FAR1 *)buffer, length);
  1454. /* read syndrom to let it through the ECC unit */
  1455. if ((NFDC21thisVars->if_cfg == 16) && (flash->interleaving == 2))
  1456. {
  1457. /* Partial page read with EDC must let rest of page through
  1458. the HW edc mechanism */
  1459. for (;unreadBytes > 0;unreadBytes -=2)
  1460. {
  1461. tmp = flRead16bitRegPlus(flash, NFDC21thisIO);
  1462. }
  1463. /* read syndrom using 16 bits access */
  1464. for (tmp=0; tmp<SYNDROM_BYTES-2; tmp+=2) /* read the 4 syndrome */
  1465. *(word *)(syndrom+tmp) = flRead16bitRegPlus(flash, NFDC21thisIO); /* bytes & store them */
  1466. /* If this is the last data read from this page read the last 2 bytes
  1467. from a dedicated register otherwise from NFDC IO register */
  1468. *(word *)(syndrom + SYNDROM_BYTES - 2) = (endHere == TRUE) ?
  1469. flRead16bitRegPlus(flash, NreadLastData_1):
  1470. flRead16bitRegPlus(flash, NFDC21thisIO);
  1471. }
  1472. else
  1473. {
  1474. /* Partial page read with EDC must let rest of page through
  1475. the HW edc mechanism */
  1476. for (;unreadBytes > 0;unreadBytes--)
  1477. {
  1478. tmp = flRead8bitRegPlus(flash, NFDC21thisIO);
  1479. }
  1480. /* read syndrom using 8 bits access */
  1481. for (tmp=0; tmp<SYNDROM_BYTES-2; tmp++) /* read the 4 syndrome */
  1482. syndrom[tmp] = flRead8bitRegPlus(flash, NFDC21thisIO); /* bytes & store them */
  1483. /* If this is the last data read from this page read the last 2 bytes
  1484. from a dedicated register */
  1485. for (tmp=SYNDROM_BYTES-2;tmp<SYNDROM_BYTES;tmp++)
  1486. syndrom[tmp] = flRead8bitRegPlus(flash, (word)(((endHere == TRUE) ?
  1487. NreadLastData_1 : NFDC21thisIO)));
  1488. }
  1489. if( eccError(flash) )
  1490. { /* try to fix ECC error */
  1491. #ifdef LOG_FILE
  1492. out=FL_FOPEN("EDCerr.txt","a");
  1493. FL_FPRINTF(out,"error on address %lx\n",address);
  1494. FL_FCLOSE(out);
  1495. #endif /* LOG_FILE */
  1496. if ( modes & NO_SECOND_TRY ) /* 2nd try */
  1497. {
  1498. #ifdef LOG_FILE
  1499. out=FL_FOPEN("EDCerr.txt","a");
  1500. FL_FPRINTF(out,"second read failed as well on address %lx",address);
  1501. #endif /* LOG_FILE */
  1502. if (NFDC21thisVars->if_cfg != 16)
  1503. {
  1504. /* read syndrom using 8 bits access */
  1505. for(modes=0; modes<SYNDROM_BYTES; modes++)
  1506. syndrom[modes] = flRead8bitRegPlus(flash,(word)(Nsyndrom+modes));
  1507. }
  1508. else
  1509. {
  1510. /* read syndrom using 16 bits access */
  1511. for(modes=0; modes<SYNDROM_BYTES; modes+=2)
  1512. *(word *)(syndrom + modes) = flRead16bitRegPlus(flash,(word)(Nsyndrom+modes));
  1513. }
  1514. tmp = (word)syndrom[0]; /* Swap 1 and 3 words */
  1515. syndrom[0] = syndrom[4];
  1516. syndrom[4] = (byte)tmp;
  1517. tmp = (word)syndrom[1];
  1518. syndrom[1] = syndrom[5];
  1519. syndrom[5] = (byte)tmp;
  1520. if(flCheckAndFixEDC((char FAR1 *)buffer,(char*)syndrom, 1) !=
  1521. NO_EDC_ERROR)
  1522. {
  1523. #ifdef LOG_FILE
  1524. FL_FPRINTF(out," Could not be fixed\n");
  1525. FL_FCLOSE(out);
  1526. #endif /* LOG_FILE */
  1527. DEBUG_PRINT(("Debug: EDC error for NFDC MDOCP.\r\n"));
  1528. return flDataError;
  1529. }
  1530. #ifdef LOG_FILE
  1531. FL_FPRINTF(out," But is was fixed\n");
  1532. FL_FCLOSE(out);
  1533. #endif /* LOG_FILE */
  1534. }
  1535. else /* 1st try - try once more */
  1536. {
  1537. status = readCommand(flash, address, cmd);
  1538. if(status != flOK)
  1539. return status;
  1540. rdBufS(flash, SECTOR_SIZE);
  1541. return readDataPlusEDC(flash,buffer,length,(word)(modes | NO_SECOND_TRY),address,cmd,endHere);
  1542. }
  1543. }
  1544. eccOFF(flash);
  1545. return flOK;
  1546. }
  1547. #endif /* NO_EDC_MODE */
  1548. /*----------------------------------------------------------------------*/
  1549. /* s e t E x t r a P t r */
  1550. /* */
  1551. /* Calculate the physical address and page offset according to the */
  1552. /* logical address given with an EXTRA mode flag */
  1553. /* */
  1554. /* Parameters: */
  1555. /* flash : Pointer identifying drive */
  1556. /* offset : Logical page offset given to the MTD */
  1557. /* length : Size to write\read (migh have implication) */
  1558. /* */
  1559. /* Return: */
  1560. /* cmd : Returns the page area. */
  1561. /* offset : Physical offset of the page. */
  1562. /*----------------------------------------------------------------------*/
  1563. /*****************************************************************************/
  1564. /* 0-5 | 6-7 | 518-519 |512-517| 8-15 | 520-527 */
  1565. /*****************************************************************************/
  1566. /* 0-2 | 3 | 4 | 5-7 | 8-11 | 12-15 */
  1567. /* edc 0 | sector flag 0 | sector flag 1 | edc 1 | unit data 0 | unit data 1 */
  1568. /*****************************************************************************/
  1569. /* AREA_B | AREA_C */
  1570. /*****************************************************************************/
  1571. static void setExtraPtr(FLFlash * flash, word * offset, dword length,
  1572. Reg8bitType * cmd)
  1573. {
  1574. *cmd = AREA_C;
  1575. if (*offset >= SECTOR_SIZE) /* Second sector */
  1576. {
  1577. *offset &= SECTOR_SIZE_MASK; /* sector offset */
  1578. if (*offset < EDC_PLUS_SECTOR_FLAGS ) /* not unit data */
  1579. {
  1580. if ((*offset >= EDC_SIZE) || /* start after edc area */
  1581. (*offset + length > EDC_SIZE)) /* or with sector flags */
  1582. {
  1583. *offset = SECOND_SECTOR_FLAGS_OFFSET; /* sector flags */
  1584. *cmd = AREA_B;
  1585. }
  1586. else /* Only edc of second sector */
  1587. {
  1588. *offset += END_OF_SECOND_SECTOR_DATA; /* area c + 10 */
  1589. }
  1590. }
  1591. else /* unit data */
  1592. {
  1593. *offset += UNIT_DATA_OFFSET; /* after first sector unit data (area c) */
  1594. }
  1595. }
  1596. else /* First sector */
  1597. {
  1598. if (flash->interleaving==2) /* otherwise do not change offset */
  1599. {
  1600. if (*offset < EDC_PLUS_SECTOR_FLAGS) /* not unit data */
  1601. {
  1602. *cmd = AREA_B; /* start from edc */
  1603. } /* if it is unit data keep offset as is in area c */
  1604. else
  1605. {
  1606. *offset += UNIT_DATA_OFFSET_MINUS_8; /* minus current offset */
  1607. }
  1608. }
  1609. }
  1610. }
  1611. /*----------------------------------------------------------------------*/
  1612. /* s e t S e c t o r D a t a P t r */
  1613. /* */
  1614. /* Calculate the physical area and offset according to the logical */
  1615. /* address given when no area mode flags was given (sector data area). */
  1616. /* */
  1617. /* Parameters: */
  1618. /* flash : Pointer identifying drive */
  1619. /* offset : Logical offset send to the MTD */
  1620. /* markFlag : True if the sector flags need to be addressed */
  1621. /* */
  1622. /* Return: */
  1623. /* cmd : Returns the page area. */
  1624. /* offset : Physical offset of the page. */
  1625. /*----------------------------------------------------------------------*/
  1626. static void setSectorDataPtr(FLFlash * flash,word * offset,Reg8bitType * cmd,
  1627. FLBoolean markFlag)
  1628. {
  1629. if (*offset >= SECTOR_SIZE) /* second sector */
  1630. {
  1631. if ((markFlag)&&(*offset == SECTOR_SIZE)) /* write operation */
  1632. {
  1633. *offset = SECOND_SECTOR_FLAGS_OFFSET; /* Write sector flags first */
  1634. *cmd = AREA_B;
  1635. return;
  1636. }
  1637. else
  1638. {
  1639. *offset += START_OF_SECOND_SECTOR_DATA; /* Start from actual data */
  1640. }
  1641. }
  1642. if (*offset < NFDC21thisVars->pageAreaSize)
  1643. {
  1644. *cmd = AREA_A;
  1645. }
  1646. else if (*offset < flash->pageSize)
  1647. {
  1648. *cmd = AREA_B;
  1649. }
  1650. else
  1651. {
  1652. *cmd = AREA_C;
  1653. }
  1654. *offset &= (NFDC21thisVars->pageAreaSize-1);
  1655. }
  1656. /*----------------------------------------------------------------------*/
  1657. /* r e a d E x t r a A r e a */
  1658. /* */
  1659. /* Read from the extra area. */
  1660. /* */
  1661. /* Note - Only the last 2 bytes are read from the pipeline (not 4). */
  1662. /* */
  1663. /* Parameters: */
  1664. /* flash : Pointer identifying drive */
  1665. /* address : Physical flash address */
  1666. /* buffer : Buffer to write from */
  1667. /* length : Size to write */
  1668. /* */
  1669. /* Return: */
  1670. /* FLStatus : 0 on success, otherwise failed. */
  1671. /*----------------------------------------------------------------------*/
  1672. static FLStatus readExtraArea (FLFlash * flash, dword address,
  1673. void FAR1 *buffer, dword length)
  1674. {
  1675. FLStatus status;
  1676. word offset = (word)(address & NFDC21thisVars->pageMask);
  1677. word savedOffset = (word)(offset & (SECTOR_SIZE-1));
  1678. word readNow;
  1679. byte cmd;
  1680. /* Arg check */
  1681. if (length + savedOffset > 16)
  1682. return flBadLength;
  1683. /* Calculate page offset and address */
  1684. setExtraPtr(flash, &offset, length , &cmd);
  1685. address = (address & ~NFDC21thisVars->pageMask) + offset;
  1686. /* Set flash to write mode and pointer to repective page ofset */
  1687. status = readCommand(flash, address, cmd);
  1688. if(status != flOK)
  1689. return status;
  1690. if (flash->interleaving == 1)
  1691. {
  1692. readNow = (word)TFFSMIN((word)(TOTAL_EXTRA_AREA - savedOffset), length);
  1693. rdBuf (flash, buffer, readNow);
  1694. length -= readNow;
  1695. }
  1696. else
  1697. {
  1698. if (cmd == AREA_C) /* unit data / second sector edc */
  1699. {
  1700. if (offset >= EDC_PLUS_SECTOR_FLAGS) /* either sectors unit data */
  1701. {
  1702. readNow = (word)TFFSMIN((word)(TOTAL_EXTRA_AREA - savedOffset), length);
  1703. }
  1704. else /* only edc data (already verified in setExtraAreaPtr */
  1705. {
  1706. readNow = (word)TFFSMIN((word)(EDC_SIZE - savedOffset), length);
  1707. }
  1708. rdBuf (flash, buffer, readNow);
  1709. length -= readNow;
  1710. }
  1711. else /* first sector edc / both sectors sector flags */
  1712. {
  1713. if (offset < EDC_PLUS_SECTOR_FLAGS) /* start from first sector */
  1714. {
  1715. readNow = (word)TFFSMIN((word)(EDC_PLUS_SECTOR_FLAGS - savedOffset), length);
  1716. rdBuf (flash, buffer, readNow);
  1717. length -= readNow;
  1718. if (length > 0) /* continue to sector unit data area */
  1719. {
  1720. return readExtraArea(flash,address - offset +
  1721. EDC_PLUS_SECTOR_FLAGS,
  1722. addToFarPointer(buffer,readNow),length);
  1723. }
  1724. }
  1725. else /* Start form sector flags of second sector */
  1726. {
  1727. /* Switch sector flags to be compatible with interleave 2 */
  1728. rdBuf (flash, BYTE_ADD_FAR(buffer,EDC_SIZE - savedOffset), SECTOR_FLAG_SIZE);
  1729. length -= SECTOR_FLAG_SIZE;
  1730. if (length > 0) /* continue with edc data of second sector */
  1731. {
  1732. readNow = (EDC_SIZE - savedOffset);
  1733. address = address - offset + savedOffset + SECTOR_SIZE;
  1734. if (readNow > 0)
  1735. {
  1736. status = readExtraArea(flash,address,buffer,readNow);
  1737. if(status != flOK)
  1738. return status;
  1739. length -= readNow;
  1740. }
  1741. if (length > 0) /* continue with unit data of second sector */
  1742. {
  1743. readNow = (word)TFFSMIN(UNIT_DATA_SIZE, length);
  1744. return readExtraArea(flash,address - savedOffset +
  1745. UNIT_DATA_SIZE,addToFarPointer(buffer,
  1746. EDC_PLUS_SECTOR_FLAGS - savedOffset),readNow);
  1747. }
  1748. }
  1749. }
  1750. }
  1751. }
  1752. selectChip(flash,MPLUS_SEL_WP);
  1753. return flOK;
  1754. }
  1755. /*----------------------------------------------------------------------*/
  1756. /* r e a d S e c t o r D a t a */
  1757. /* */
  1758. /* Read sector data from the page. */
  1759. /* */
  1760. /* Parameters: */
  1761. /* flash : Pointer identifying drive */
  1762. /* address : Physical flash address */
  1763. /* buffer : Buffer to write from */
  1764. /* length : Size to write */
  1765. /* edc : EDC to add edc after data and write sector flags */
  1766. /* */
  1767. /* Note: Sector flags area written automaticly as 0x55 , 0x55. */
  1768. /* Note: Sector flags are written only if edc is on. */
  1769. /* */
  1770. /* Note - Only the last 2 bytes are read from the pipeline (not 4). */
  1771. /* */
  1772. /* Return: */
  1773. /* FLStatus : 0 on success, otherwise failed. */
  1774. /*----------------------------------------------------------------------*/
  1775. static FLStatus readSectorData(FLFlash * flash, CardAddress address,
  1776. byte FAR1 *buffer, dword length, word modes)
  1777. {
  1778. word offset = (word)(address & NFDC21thisVars->pageMask);
  1779. word savedOffset = offset;
  1780. word lenInPage = (word)TFFSMIN(length, (dword)(flash->pageSize - savedOffset));
  1781. word readNow = 0; /* Initialized to remove warrnings */
  1782. byte cmd;
  1783. FLStatus status;
  1784. register int i;
  1785. /******************************************************/
  1786. /* Loop over pages while reading the proper area data */
  1787. /******************************************************/
  1788. setSectorDataPtr(flash,&offset , &cmd,0);
  1789. address = (address & ~NFDC21thisVars->pageMask) + offset;
  1790. while (length > 0)
  1791. {
  1792. /* Set flash to write mode and pointer to repective page offset */
  1793. status = readCommand(flash, address, cmd);
  1794. if(status != flOK)
  1795. return status;
  1796. /* Calculate the bytes neaded to be read from this page */
  1797. length -= lenInPage;
  1798. /* Send read pipeline init */
  1799. rdBufS(flash, lenInPage);
  1800. /* Read First sector of page */
  1801. if ((cmd == AREA_A) || (flash->interleaving == 1))
  1802. {
  1803. readNow = (word)TFFSMIN((word)(SECTOR_SIZE - savedOffset), lenInPage);
  1804. /* EDC and sector flags 0x5555 are written only if EDC is required.
  1805. * and a full 512 bytes area written */
  1806. #ifndef NO_EDC_MODE
  1807. if ( /* Full 512 bytes + EDC requested */
  1808. ((readNow == SECTOR_SIZE) && (modes & EDC)) ||
  1809. /* Partial page with EDC requested */
  1810. ((modes == PARTIAL_EDC) && (savedOffset == 0)))
  1811. {
  1812. status = readDataPlusEDC(flash,buffer,readNow,modes,address,
  1813. cmd,(lenInPage == readNow) ? TRUE:FALSE);
  1814. if(status != flOK)
  1815. return status;
  1816. }
  1817. else
  1818. #endif /* NO_EDC_MODE */
  1819. {
  1820. /* user data (the last 2 bytes are read from a diffrent register */
  1821. word realyReadNow = (word)((lenInPage == readNow) ?
  1822. (readNow - 2) : readNow);
  1823. docPlusRead(flash->win,NFDC21thisIO,buffer,realyReadNow);
  1824. }
  1825. lenInPage -= readNow;
  1826. }
  1827. /* Read Second sector of page */
  1828. if ((lenInPage > 0)&&(flash->interleaving==2))
  1829. {
  1830. if (cmd == AREA_A) /* Started from first sector */
  1831. {
  1832. byte tmpBuf[10];
  1833. #ifndef NO_EDC_MODE
  1834. if ((readNow != SECTOR_SIZE) || /* not Full 512 bytes */
  1835. !(modes & EDC)) /* or EDC not requesed */
  1836. #endif /* NO_EDC_MODE */
  1837. {
  1838. docPlusRead(flash->win,NFDC21thisIO,tmpBuf, EDC_SIZE); /* skip edc and sector flags */
  1839. }
  1840. docPlusRead(flash->win,NFDC21thisIO,tmpBuf, SECTOR_FLAG_SIZE<<1); /* skip 2 sector flags */
  1841. buffer = BYTE_ADD_FAR(buffer,readNow);
  1842. savedOffset = SECTOR_SIZE;
  1843. address += (readNow+START_OF_SECOND_SECTOR_DATA);
  1844. cmd = AREA_B;
  1845. }
  1846. readNow = lenInPage;
  1847. #ifndef NO_EDC_MODE
  1848. if ( /* Full 512 bytes + EDC requested */
  1849. ((readNow == SECTOR_SIZE) && (modes & EDC)) ||
  1850. /* Partial page with EDC requested */
  1851. ((savedOffset == SECTOR_SIZE) && (modes & PARTIAL_EDC)) )
  1852. {
  1853. status = readDataPlusEDC(flash,buffer,readNow,modes,address,
  1854. cmd,(lenInPage == readNow) ? TRUE:FALSE);
  1855. if(status != flOK)
  1856. return status;
  1857. }
  1858. else
  1859. #endif /* NO_EDC_MODE */
  1860. {
  1861. /* user data (the last 2 bytes are read from a diffrent register */
  1862. docPlusRead(flash->win,NFDC21thisIO,buffer, (word)((lenInPage == readNow) ?
  1863. (readNow - 2) : readNow));
  1864. }
  1865. }
  1866. #ifndef NO_EDC_MODE
  1867. /* If no EDC, Read last data from dedicated register */
  1868. if (((modes & EDC) == 0) || /* EDC not requesed */
  1869. ((readNow != SECTOR_SIZE) && /* not Full 512 bytes */
  1870. ((modes & PARTIAL_EDC) == 0))) /* And not PARTIAL page EDC */
  1871. #endif /* NO_EDC_MODE */
  1872. {
  1873. if ((NFDC21thisVars->if_cfg == 16) && (flash->interleaving == 2))
  1874. {
  1875. volatile Reg16bitType junkWord;
  1876. /* Before reading the last data perform dummy read cycles */
  1877. for (i=0; i< ((readNow >> (flash->interleaving -1)) > 1 ?0:2); i++)
  1878. offset = flRead16bitRegPlus(flash, NreadLastData_1); /* junk */
  1879. /* Now read the data from the last data read register make
  1880. sure not to cast pointer to word since it might not be
  1881. word aligned */
  1882. junkWord = flRead16bitRegPlus(flash, NreadLastData_1);
  1883. *BYTE_ADD_FAR(buffer,readNow-2) = ((byte FAR1*)(&junkWord))[0];
  1884. *BYTE_ADD_FAR(buffer,readNow-1) = ((byte FAR1*)(&junkWord))[1];
  1885. }
  1886. else
  1887. {
  1888. /* Before reading the last data perform dummy read cycles */
  1889. for (i=0; ( i < ((readNow >> (flash->interleaving -1)) > 1 ?
  1890. 0 : ((flash->interleaving == 2) ? 4:2)));i++)
  1891. cmd = flRead8bitRegPlus(flash, NreadLastData_1); /* junk */
  1892. /* Now read the data from the last data read register */
  1893. for (i=2;i>0;i--)
  1894. {
  1895. *BYTE_ADD_FAR(buffer,readNow-i) = flRead8bitRegPlus(flash, NreadLastData_1);
  1896. }
  1897. }
  1898. }
  1899. /* Calculate next address and page offset */
  1900. if (length > 0)
  1901. {
  1902. buffer = BYTE_ADD_FAR(buffer,readNow);
  1903. address = (address & (~NFDC21thisVars->pageMask)) + flash->pageSize;
  1904. lenInPage = (word)TFFSMIN(length,flash->pageSize);
  1905. savedOffset = 0;
  1906. cmd = AREA_A;
  1907. }
  1908. selectChip(flash,MPLUS_SEL_WP);
  1909. }
  1910. return flOK;
  1911. }
  1912. /*----------------------------------------------------------------------*/
  1913. /* d o c 2 R e a d */
  1914. /* */
  1915. /* Read some data from the flash. This routine will be registered as */
  1916. /* the read routine for this MTD. */
  1917. /* */
  1918. /* Note - address + length must reside inside media. */
  1919. /* Note - global variables changed: */
  1920. /* global variable NFDC21thisVars->currentFloor is updated */
  1921. /* flash->socket.window.currentPage = pageToMap; */
  1922. /* flash->socket.remapped = TRUE; */
  1923. /* */
  1924. /* Note - PARTIAL_EDC mode must not be called with an uneven number of */
  1925. /* bytes. */
  1926. /* */
  1927. /* Parameters: */
  1928. /* flash : Pointer identifying drive */
  1929. /* address : Address of sector to write to. */
  1930. /* buffer : buffer to write from. */
  1931. /* length : number of bytes to write. */
  1932. /* modes : EDC / EXTRA flags. */
  1933. /* */
  1934. /* Returns: */
  1935. /* FLStatus : 0 on success, otherwise failed. */
  1936. /*----------------------------------------------------------------------*/
  1937. static FLStatus doc2Read(FLFlash * flash, CardAddress address,
  1938. void FAR1 *buffer, dword length, word modes)
  1939. {
  1940. FLStatus status;
  1941. byte align[2];
  1942. #ifdef ENVIRONMENT_VARS
  1943. if((flSuspendMode & FL_SUSPEND_IO) == FL_SUSPEND_IO)
  1944. return flIOCommandBlocked;
  1945. #endif /* ENVIRONMENT_VARS */
  1946. if (address & 1) /* Start from uneven address */
  1947. {
  1948. status = doc2Read(flash,address-1,align,2,0);
  1949. if(status != flOK)
  1950. return status;
  1951. *(byte FAR1*)buffer = align[1];
  1952. buffer = BYTE_ADD_FAR(buffer,1);
  1953. address++;
  1954. length--;
  1955. }
  1956. if (length & 1) /* Read an uneven length */
  1957. {
  1958. length--;
  1959. status = doc2Read(flash,address+length,align,2,modes);
  1960. if(status != flOK)
  1961. return status;
  1962. *BYTE_ADD_FAR(buffer,length) = align[0];
  1963. }
  1964. if(modes & EXTRA) /* EXTRA AREA */
  1965. {
  1966. return readExtraArea(flash,address, buffer , length);
  1967. }
  1968. else
  1969. {
  1970. return readSectorData(flash,address, (byte FAR1 *)buffer, length , modes);
  1971. }
  1972. }
  1973. #ifndef FL_READ_ONLY
  1974. /*----------------------------------------------------------------------*/
  1975. /* w r i t e E x t r a A r e a */
  1976. /* */
  1977. /* Write to the extra area. */
  1978. /* */
  1979. /* Parameters: */
  1980. /* flash : Pointer identifying drive */
  1981. /* address : Physical flash address */
  1982. /* buffer : Buffer to write from */
  1983. /* length : Size to write */
  1984. /* */
  1985. /* Return: */
  1986. /* FLStatus : 0 on success, otherwise failed. */
  1987. /*----------------------------------------------------------------------*/
  1988. static FLStatus writeExtraArea (FLFlash * flash, dword address,
  1989. const void FAR1 *buffer, dword length)
  1990. {
  1991. word offset = (word)(address & NFDC21thisVars->pageMask);
  1992. word savedOffset = (word)(offset & (SECTOR_SIZE-1));
  1993. word writeNow = 0;
  1994. FLStatus status;
  1995. byte sectorFlags [2];
  1996. byte cmd;
  1997. /* Calculate page offset */
  1998. setExtraPtr(flash, &offset, length , &cmd);
  1999. address = (address & ~NFDC21thisVars->pageMask) + offset;
  2000. /* Set flash to write mode and pointer to repective page ofset */
  2001. status = writeCommand(flash, address, cmd);
  2002. if(status != flOK)
  2003. return status;
  2004. if (flash->interleaving == 1)
  2005. {
  2006. writeNow = (word)TFFSMIN((byte)(TOTAL_EXTRA_AREA - savedOffset), length);
  2007. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)buffer, writeNow);
  2008. length -= writeNow;
  2009. }
  2010. else
  2011. {
  2012. if (cmd == AREA_C) /* unit data / second sector edc */
  2013. {
  2014. if (offset >= EDC_PLUS_SECTOR_FLAGS) /* either sectors unit data */
  2015. {
  2016. writeNow = (word)TFFSMIN((byte)(TOTAL_EXTRA_AREA - savedOffset), length);
  2017. }
  2018. else /* only edc data (already verified in setExtraAreaPtr */
  2019. {
  2020. writeNow = (word)TFFSMIN((byte)(EDC_PLUS_SECTOR_FLAGS - savedOffset), length);
  2021. }
  2022. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)buffer, writeNow);
  2023. length -= writeNow;
  2024. }
  2025. else /* first sector edc + both sectors sector flags */
  2026. {
  2027. if (offset < EDC_PLUS_SECTOR_FLAGS)
  2028. {
  2029. /* start from first sector edc and sector flags */
  2030. writeNow = (word)TFFSMIN((byte)(EDC_PLUS_SECTOR_FLAGS - savedOffset), length);
  2031. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)buffer, writeNow);
  2032. length -= writeNow;
  2033. if (length > 0) /* continue to sector unit data area */
  2034. {
  2035. buffer = addToFarPointer(buffer,writeNow);
  2036. /* skip second sector to reach the unit data area */
  2037. docPlusSet(flash->win,NFDC21thisIO,SECTOR_SIZE+EDC_PLUS_SECTOR_FLAGS,0xff);
  2038. /* unit data */
  2039. writeNow = (word)TFFSMIN(UNIT_DATA_SIZE , length);
  2040. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)buffer, writeNow);
  2041. length -= writeNow;
  2042. }
  2043. }
  2044. else /* Start form sector flags of second sector */
  2045. {
  2046. /* Switch sector flags to be compatible with interleave 2 */
  2047. sectorFlags[0] = *BYTE_ADD_FAR(buffer,6 - savedOffset);
  2048. sectorFlags[1] = *BYTE_ADD_FAR(buffer,7 - savedOffset);
  2049. #ifndef NT5PORT
  2050. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)&sectorFlags, SECTOR_FLAG_SIZE);
  2051. #else /*NT5PORT*/
  2052. docPlusWrite(flash->win,NFDC21thisIO, sectorFlags, SECTOR_FLAG_SIZE);
  2053. #endif /*NT5PORT*/
  2054. length -= SECTOR_FLAG_SIZE;
  2055. if (length > 0) /* continue with edc data of second sector */
  2056. {
  2057. docPlusSet (flash->win,NFDC21thisIO, (word)(SECTOR_SIZE + savedOffset), 0xff); /* skip second sector data */
  2058. /* + offset in edc */
  2059. writeNow = EDC_SIZE - savedOffset;
  2060. docPlusWrite(flash->win, NFDC21thisIO, (byte FAR1 *)buffer, writeNow);
  2061. length -= writeNow;
  2062. if (length > 0) /* continue with unit data of second sector */
  2063. {
  2064. buffer = addToFarPointer(buffer,writeNow+SECTOR_FLAG_SIZE);
  2065. docPlusSet (flash->win, NFDC21thisIO, UNIT_DATA_SIZE, 0xff); /* skip second sector unit data */
  2066. writeNow = (word)TFFSMIN(UNIT_DATA_SIZE, length);
  2067. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)buffer, writeNow);
  2068. length -= writeNow;
  2069. }
  2070. }
  2071. }
  2072. }
  2073. }
  2074. /* Exit nicly */
  2075. if (length > 0 )
  2076. {
  2077. return flBadLength;
  2078. }
  2079. else /* Commit data to flash */
  2080. {
  2081. return writeExecute (flash);
  2082. }
  2083. }
  2084. /*----------------------------------------------------------------------*/
  2085. /* w r i t e S e c t o r D a t a */
  2086. /* */
  2087. /* Write sector data of the page. */
  2088. /* */
  2089. /* Parameters: */
  2090. /* flash : Pointer identifying drive */
  2091. /* address : Physical flash address */
  2092. /* buffer : Buffer to write from */
  2093. /* length : Size to write */
  2094. /* edc : EDC to add edc after data and write sector flags */
  2095. /* */
  2096. /* Return: */
  2097. /* FLStatus : 0 on success, otherwise failed. */
  2098. /*----------------------------------------------------------------------*/
  2099. static FLStatus writeSectorData(FLFlash * flash, CardAddress address,
  2100. const byte FAR1 *buffer, dword length,
  2101. unsigned edc)
  2102. {
  2103. static byte anandMark[2] = { 0x55, 0x55 };
  2104. FLStatus status;
  2105. word offset = (word)(address & NFDC21thisVars->pageMask);
  2106. word savedOffset = offset;
  2107. word writeNow = 0; /* Initialized to remove warrnings */
  2108. byte cmd;
  2109. /*******************************************************/
  2110. /* Loop over pages while writting the proper area data */
  2111. /*******************************************************/
  2112. setSectorDataPtr(flash,&offset , &cmd, ((edc & EDC) &&
  2113. (length >= SECTOR_SIZE)) ? TRUE:FALSE);
  2114. address = (address & ~NFDC21thisVars->pageMask) + offset;
  2115. while (length > 0)
  2116. {
  2117. /* Set flash to write mode and pointer to repective page ofset */
  2118. status = writeCommand(flash, address, cmd);
  2119. if(status != flOK)
  2120. return status;
  2121. /* Write First sector of page */
  2122. if ((cmd == AREA_A)||(flash->interleaving==1))
  2123. {
  2124. writeNow = (word)TFFSMIN((word)(SECTOR_SIZE - savedOffset), length);
  2125. length -= writeNow;
  2126. /* EDC and sector flags 0x5555 are written only if EDC is required.
  2127. * and a full 512 bytes area written */
  2128. #ifndef NO_EDC_MODE
  2129. if ((writeNow == SECTOR_SIZE) && /* Full 512 bytes */
  2130. (edc == EDC)) /* And EDC is requesed */
  2131. {
  2132. writeDataPlusEDC(flash,buffer);
  2133. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)anandMark, sizeof(anandMark)); /* sector used */
  2134. }
  2135. else
  2136. #endif /* NO_EDC_MODE */
  2137. {
  2138. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)buffer, writeNow); /* user data */
  2139. }
  2140. }
  2141. /* Write Second sector of page */
  2142. if ((length > 0)&&(flash->interleaving==2))
  2143. {
  2144. /* Skip to begining of sector */
  2145. if (cmd == AREA_A) /* Started from first sector */
  2146. {
  2147. #ifndef NO_EDC_MODE
  2148. if ((writeNow != SECTOR_SIZE) || /* not Full 512 bytes */
  2149. (edc != EDC)) /* or EDC not requesed */
  2150. #endif /* NO_EDC_MODE */
  2151. {
  2152. docPlusSet (flash->win, NFDC21thisIO, EDC_PLUS_SECTOR_FLAGS, 0xff); /* skip edc and sector flags */
  2153. }
  2154. buffer = BYTE_ADD_FAR(buffer,writeNow);
  2155. savedOffset = SECTOR_SIZE;
  2156. }
  2157. /* Read sector data */
  2158. writeNow = (word)TFFSMIN((word)(flash->pageSize - savedOffset) , length);
  2159. #ifndef NO_EDC_MODE
  2160. if ((writeNow == SECTOR_SIZE) && /* Full 512 bytes */
  2161. (edc == EDC)) /* And EDC is requesed */
  2162. {
  2163. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)anandMark, sizeof(anandMark)); /* sector used */
  2164. writeDataPlusEDC(flash,buffer);
  2165. }
  2166. else
  2167. #endif /* NO_EDC_MODE */
  2168. {
  2169. if ((savedOffset == SECTOR_SIZE)&&(cmd==AREA_A))
  2170. docPlusSet(flash->win, NFDC21thisIO,sizeof(anandMark),0xff); /* Skip sector flags */
  2171. docPlusWrite(flash->win,NFDC21thisIO, (byte FAR1 *)buffer, writeNow); /* user data */
  2172. }
  2173. length -= writeNow;
  2174. }
  2175. /* Incremeant buffer and address */
  2176. buffer = BYTE_ADD_FAR(buffer,writeNow);
  2177. address = (address & (~NFDC21thisVars->pageMask)) + flash->pageSize;
  2178. savedOffset = 0;
  2179. cmd = AREA_A;
  2180. /* Commit operation */
  2181. status = writeExecute(flash);
  2182. if(status != flOK)
  2183. return status;
  2184. }
  2185. return flOK;
  2186. }
  2187. /*----------------------------------------------------------------------*/
  2188. /* d o c 2 W r i t e */
  2189. /* */
  2190. /* Write some data to the flash. This routine will be registered as the */
  2191. /* write routine for this MTD. */
  2192. /* */
  2193. /* Note - address + length must reside inside media. */
  2194. /* Note - global variables changed: */
  2195. /* global variable NFDC21thisVars->currentFloor is updated */
  2196. /* flash->socket.window.currentPage = pageToMap; */
  2197. /* flash->socket.remapped = TRUE; */
  2198. /* */
  2199. /* Parameters: */
  2200. /* flash : Pointer identifying drive */
  2201. /* address : Address of sector to write to. */
  2202. /* buffer : buffer to write from. */
  2203. /* length : number of bytes to write. */
  2204. /* modes : EDC flags. */
  2205. /* */
  2206. /* Returns: */
  2207. /* FLStatus : 0 on success, otherwise failed. */
  2208. /*----------------------------------------------------------------------*/
  2209. static FLStatus doc2Write(FLFlash * flash, CardAddress address,
  2210. const void FAR1 *buffer, dword length, word modes)
  2211. {
  2212. FLStatus status;
  2213. byte align[2];
  2214. #ifdef ENVIRONMENT_VARS
  2215. if(flSuspendMode & FL_SUSPEND_WRITE)
  2216. return flIOCommandBlocked;
  2217. #endif /* ENVIRONMENT_VARS */
  2218. #ifndef MTD_STANDALONE
  2219. /* Check if socket is software write protected */
  2220. if (flWriteProtected(flash->socket))
  2221. return( flWriteProtect );
  2222. #endif /* MTD_STANDALONE */
  2223. if (address & 1) /* Start from uneven address */
  2224. {
  2225. align[1] = *(byte FAR1*)buffer;
  2226. align[0] = 0xff;
  2227. #ifdef VERIFY_WRITE
  2228. if (modes & EXTRA) /* EXTRA AREA */
  2229. {
  2230. status = writeExtraArea(flash,address-1, align , 2);
  2231. }
  2232. else
  2233. {
  2234. status = writeSectorData(flash,address-1,
  2235. (const byte FAR1 *)align,2,modes);
  2236. }
  2237. if(status != flOK)
  2238. {
  2239. /* Restore flash write protection */
  2240. selectChip(flash,MPLUS_SEL_WP); /* write protect all chips */
  2241. }
  2242. checkStatus(doc2Read(flash,address-1,align,2,modes));
  2243. if(align[1] != *(byte FAR1*)buffer)
  2244. {
  2245. DEBUG_PRINT(("reading back data failure of first unaligned byte\r\n"));
  2246. return flWriteFault;
  2247. }
  2248. #else
  2249. checkStatus(doc2Write(flash,address-1,align,2,modes));
  2250. #endif /* VERIFY_WRITE */
  2251. buffer = BYTE_ADD_FAR(buffer,1);
  2252. address++;
  2253. length--;
  2254. }
  2255. if (length & 1) /* Write an uneven length */
  2256. {
  2257. length--;
  2258. align[0] = *BYTE_ADD_FAR(buffer,length);
  2259. align[1] = 0xff;
  2260. #ifdef VERIFY_WRITE
  2261. if (modes & EXTRA) /* EXTRA AREA */
  2262. {
  2263. status = writeExtraArea(flash,address+length, align , 2);
  2264. }
  2265. else
  2266. {
  2267. status = writeSectorData(flash,address+length,
  2268. (const byte FAR1 *)align,2,modes);
  2269. }
  2270. if(status != flOK)
  2271. {
  2272. /* Restore flash write protection */
  2273. selectChip(flash,MPLUS_SEL_WP); /* write protect all chips */
  2274. }
  2275. checkStatus(doc2Read(flash,address+length,align,2,modes));
  2276. if(align[0] != *BYTE_ADD_FAR(buffer,length))
  2277. {
  2278. DEBUG_PRINT(("reading back data failure of last unaligned byte\r\n"));
  2279. return flWriteFault;
  2280. }
  2281. #else
  2282. checkStatus(doc2Write(flash,address+length,align,2,modes));
  2283. #endif /* VERIFY_WRITE */
  2284. }
  2285. if (modes & EXTRA) /* EXTRA AREA */
  2286. {
  2287. status = writeExtraArea(flash,address, buffer , length);
  2288. }
  2289. else
  2290. {
  2291. status = writeSectorData(flash,address, (const byte FAR1 *)buffer, length , modes);
  2292. }
  2293. /* Restore flash write protection */
  2294. selectChip(flash,MPLUS_SEL_WP); /* write protect all chips */
  2295. #ifdef VERIFY_WRITE
  2296. /* Read back after write and verify */
  2297. if(
  2298. #ifndef MTD_STANDALONE
  2299. (flash->socket->verifyWrite==FL_ON) &&
  2300. #endif /* MTD_STANDALONE */
  2301. (status==flOK) )
  2302. {
  2303. word curRead = 0;
  2304. void FAR1* bufPtr = (void FAR1*)buffer;
  2305. for (;length > 0;length -= curRead,
  2306. bufPtr = BYTE_ADD_FAR(bufPtr,curRead),address+=curRead)
  2307. {
  2308. curRead = (word)TFFSMIN(length , READ_BACK_BUFFER_SIZE);
  2309. status = doc2Read(flash,address,NFDC21thisVars->readBackBuffer,curRead,modes);
  2310. if ((status != flOK) ||
  2311. (tffscmp(bufPtr,NFDC21thisVars->readBackBuffer,curRead)))
  2312. {
  2313. DEBUG_PRINT(("reading back data failure\r\n"));
  2314. return flWriteFault;
  2315. }
  2316. }
  2317. }
  2318. #endif /* VERIFY_WRITE */
  2319. return status;
  2320. }
  2321. #ifdef VERIFY_ERASE
  2322. /*----------------------------------------------------------------------*/
  2323. /* c h e c k E r a s e */
  2324. /* */
  2325. /* Check if media is truly erased (main areas of page only). */
  2326. /* */
  2327. /* Parameters: */
  2328. /* flash : Pointer identifying drive */
  2329. /* address : Address of page to check. */
  2330. /* */
  2331. /* Note - global variables changed at doc2Read: */
  2332. /* global variable NFDC21thisVars->currentFloor is updated */
  2333. /* flash->socket.window.currentPage = pageToMap; */
  2334. /* flash->socket.remapped = TRUE; */
  2335. /* */
  2336. /* Returns: */
  2337. /* FLStatus : 0 if page is erased, otherwise writeFault. */
  2338. /*----------------------------------------------------------------------*/
  2339. static FLStatus checkErase( FLFlash * flash, CardAddress address)
  2340. {
  2341. register int i, j;
  2342. word inc = READ_BACK_BUFFER_SIZE;
  2343. dword * bufPtr = (dword *)NFDC21thisVars->readBackBuffer;
  2344. CardAddress curAddress = address;
  2345. word block = (word)(flash->erasableBlockSize / inc);
  2346. dword * endBufPtr = bufPtr+(inc / sizeof(dword));
  2347. dword * curBufPtr;
  2348. /* Check main area */
  2349. for ( i = 0 ; i < block ; i++, curAddress += inc )
  2350. {
  2351. if ( doc2Read(flash,curAddress,(void FAR1 *)bufPtr,(dword)inc,0) != flOK )
  2352. return( flWriteFault );
  2353. for ( curBufPtr = bufPtr ;
  2354. curBufPtr < endBufPtr ; curBufPtr++)
  2355. if ( *bufPtr != 0xFFFFFFFFL )
  2356. return( flWriteFault );
  2357. }
  2358. /* Check extra area */
  2359. for ( i = 0 ; i < NFDC21thisVars->pagesPerBlock ; i++)
  2360. {
  2361. if ( doc2Read(flash,address,(void FAR1 *)bufPtr,
  2362. NFDC21thisVars->tailSize, EXTRA) != flOK )
  2363. return( flWriteFault );
  2364. for (j=0;j<(NFDC21thisVars->tailSize>>2);j++)
  2365. {
  2366. if (bufPtr[j] != 0xFFFFFFFFL)
  2367. return( flWriteFault );
  2368. }
  2369. }
  2370. return( flOK );
  2371. }
  2372. #endif /* VERIFY_ERASE */
  2373. /*----------------------------------------------------------------------*/
  2374. /* d o c 2 E r a s e */
  2375. /* */
  2376. /* Erase number of blocks. This routine will be registered as the */
  2377. /* erase routine for this MTD. */
  2378. /* */
  2379. /* Parameters: */
  2380. /* flash : Pointer identifying drive */
  2381. /* blockNo : First block to erase. */
  2382. /* blocksToErase : Number of blocks to erase. */
  2383. /* */
  2384. /* Note - The amount of blocks to erase must be inside media. */
  2385. /* Note - global variables changed at checkErase: */
  2386. /* global variable NFDC21thisVars->currentFloor is updated */
  2387. /* flash->socket.window.currentPage = pageToMap */
  2388. /* flash->socket.remapped = TRUE */
  2389. /* */
  2390. /* Returns: */
  2391. /* FLStatus : 0 on success, otherwise failed. */
  2392. /*----------------------------------------------------------------------*/
  2393. static FLStatus doc2Erase(FLFlash * flash, word blockNo, word blocksToErase)
  2394. {
  2395. CardAddress startAddress = (CardAddress)blockNo * flash->erasableBlockSize;
  2396. FLStatus status;
  2397. dword pageNo;
  2398. byte floorToUse = (byte)(startAddress / NFDC21thisVars->floorSize);
  2399. dword i;
  2400. word nextFloorBlockNo = (word) (((floorToUse + 1) *
  2401. NFDC21thisVars->floorSize) / flash->erasableBlockSize);
  2402. #ifdef ENVIRONMENT_VARS
  2403. if(flSuspendMode & FL_SUSPEND_WRITE)
  2404. return flIOCommandBlocked;
  2405. #endif /* ENVIRONMENT_VARS */
  2406. #ifndef MTD_STANDALONE
  2407. if (flWriteProtected(flash->socket))
  2408. return( flWriteProtect );
  2409. #endif /* MTD_STANDALONE */
  2410. /* Arg check (out of media) */
  2411. if( blockNo + blocksToErase > NFDC21thisVars->noOfBlocks * flash->noOfChips)
  2412. return( flWriteFault );
  2413. /* First erase higher floors units */
  2414. if( blockNo + blocksToErase > nextFloorBlockNo )
  2415. { /* erase on higher floors */
  2416. status = doc2Erase(flash, nextFloorBlockNo,(word)(blocksToErase -
  2417. (nextFloorBlockNo - blockNo)));
  2418. if(status != flOK)
  2419. return status;
  2420. blocksToErase = nextFloorBlockNo - blockNo;
  2421. }
  2422. /* Selet Floor */
  2423. selectFloor(flash,startAddress);
  2424. pageNo = ((dword)(blockNo % (4096 >> flash->interleaving)) * NFDC21thisVars->pagesPerBlock);
  2425. for (i = 0; (word)i < blocksToErase ; i++, pageNo+=NFDC21thisVars->pagesPerBlock)
  2426. {
  2427. /* Make sure Asic is in normal mode */
  2428. status = chkASICmode(flash);
  2429. if(status != flOK)
  2430. return status;
  2431. /* Select chip and remove write protection */
  2432. selectChip(flash,MPLUS_SEL_CE);
  2433. command (flash,RESET_FLASH); /* reset flashes */
  2434. if (waitForReady(flash)==FALSE) /* wait for ready signal */
  2435. return flTimedOut;
  2436. /* enable EDGE or LEVEL MDOC+ interrupt before the erase command */
  2437. #ifdef ENABLE_EDGE_INTERRUPT
  2438. /* enable interrupt: EDGE, clear previous interrupt, FREADY source */
  2439. flWrite8bitRegPlus(flash,NinterruptControl ,
  2440. (INTR_EDGE_MASK | INTR_IRQ_P_MASK | INTR_IRQ_F_MASK | 0x1));
  2441. #else
  2442. #ifdef ENABLE_LEVEL_INTERRUPT
  2443. /* enable interrupt: LEVEL, clear previous interrupt, FREADY source */
  2444. flWrite8bitRegPlus(flash,NinterruptControl ,
  2445. (INTR_IRQ_P_MASK | INTR_IRQ_F_MASK | 0x1));
  2446. #endif /* ENABLE_LEVEL_INTERRUPT */
  2447. #endif /* ENABLE_EDGE_INTERRUPT */
  2448. command (flash,SETUP_ERASE); /* send erase command */
  2449. /* Set address */
  2450. flWrite8bitRegPlus(flash,NflashAddress,(Reg8bitType)(pageNo));
  2451. flWrite8bitRegPlus(flash,NflashAddress,(Reg8bitType)(pageNo >> 8));
  2452. flWrite8bitRegPlus(flash,NwritePipeTerm,(Reg8bitType)0);
  2453. flWrite8bitRegPlus(flash,NwritePipeTerm,(Reg8bitType)0);
  2454. /* send the confirm erase command */
  2455. command(flash, CONFIRM_ERASE);
  2456. #ifndef MTD_STANDALONE
  2457. #ifndef DO_NOT_YIELD_CPU
  2458. if(waitForReadyWithYieldCPU(flash,MAX_WAIT)==FALSE)
  2459. #endif /* DO_NOT_YIELD_CPU */
  2460. #endif /* MTD_STANDALONE */
  2461. {
  2462. if (waitForReady(flash)==FALSE) /* wait for ready signal */
  2463. return flTimedOut;
  2464. }
  2465. if(isAccessError(flash))
  2466. {
  2467. /* Restore write proection to reduce power consumption */
  2468. selectChip(flash,MPLUS_SEL_WP);
  2469. return flHWProtection;
  2470. }
  2471. /* Validate erase command status */
  2472. if ( readStatus(flash) ) /* erase operation failed */
  2473. {
  2474. DEBUG_PRINT(("Debug: doc2Erase - erase failed.\r\n"));
  2475. /* reset flash device write protect them and abort */
  2476. command(flash, RESET_FLASH);
  2477. if (waitForReady(flash)==FALSE) /* wait for ready signal */
  2478. return flTimedOut;
  2479. selectChip(flash,MPLUS_SEL_WP);
  2480. return flWriteFault;
  2481. }
  2482. /* no failure reported */
  2483. #ifdef VERIFY_ERASE
  2484. if ( checkErase( flash, startAddress ) != flOK )
  2485. {
  2486. DEBUG_PRINT(("Debug: doc2Erase- erase failed in verification.\r\n"));
  2487. return flWriteFault ;
  2488. }
  2489. #else
  2490. /* Restore write proection */
  2491. selectChip(flash,MPLUS_SEL_WP);
  2492. #endif /* VERIFY_ERASE */
  2493. }
  2494. return flOK;
  2495. }
  2496. #endif /* FL_READ_ONLY */
  2497. #ifndef MTD_STANDALONE
  2498. /*----------------------------------------------------------------------*/
  2499. /* d o c 2 M a p */
  2500. /* */
  2501. /* Map through buffer. This routine will be registered as the map */
  2502. /* routine for this MTD. */
  2503. /* */
  2504. /* Parameters: */
  2505. /* flash : Pointer identifying drive */
  2506. /* address : Flash address to be mapped. */
  2507. /* length : number of bytes to map. */
  2508. /* */
  2509. /* Note - Size must not be greater then 512 bytes */
  2510. /* */
  2511. /* Returns: */
  2512. /* Pointer to the buffer data was mapped to. */
  2513. /* */
  2514. /*----------------------------------------------------------------------*/
  2515. static void FAR0 *doc2Map ( FLFlash * flash, CardAddress address, int length )
  2516. {
  2517. doc2Read(flash,address,NFDC21thisBuffer,length, 0);
  2518. /* Force remapping of internal catched sector */
  2519. flash->socket->remapped = TRUE;
  2520. return( (void FAR0 *)NFDC21thisBuffer );
  2521. }
  2522. #endif /* MTD_STANDALONE */
  2523. #ifdef MTD_READ_BBT
  2524. /*----------------------------------------------------------------------*/
  2525. /* R e a d B B T */
  2526. /* */
  2527. /* Read the media Bad Blocks Table to a user buffer. */
  2528. /* */
  2529. /* Parameters: */
  2530. /* flash : Pointer identifying drive */
  2531. /* unitNo : indicated which unit number to start checking from. */
  2532. /* unitToRead : indicating how many units to check */
  2533. /* buffer : buffer to read into. */
  2534. /* reconstruct : Ignored, irelevant for DiskOnChip Millennium Plus */
  2535. /* */
  2536. /* Note: blocks is a minimal flash erasable area. */
  2537. /* Note: unit can contain several blocks. */
  2538. /* Note: There is no current implementation of a unit that contains */
  2539. /* more then a single block. */
  2540. /* Note: The format of the BBT is byte per unit 0 for bad any other */
  2541. /* value for good. */
  2542. /* Note: global variables changed at doc2Read: */
  2543. /* global variable NFDC21thisVars->currentFloor is updated */
  2544. /* flash->socket.window.currentPage = pageToMap; */
  2545. /* flash->socket.remapped = TRUE; */
  2546. /* Note: At least 4 bytes must be read */
  2547. /* */
  2548. /* RETURNS: */
  2549. /* flOK on success */
  2550. /* flBadLength if one of the units is out of the units range */
  2551. /* flBadBBT on read fault */
  2552. /*----------------------------------------------------------------------*/
  2553. /* BBT format (in interleave-1) */
  2554. /* ---------- */
  2555. /* Offset 512 of the floor holds the BBT of the entire floor in the */
  2556. /* following format: */
  2557. /* (even district) (odd district) */
  2558. /* byte 0 bit 0,1 block 0 block 1024 */
  2559. /* bit 2,3 block 1 block 1025 */
  2560. /* bit 4,5 block 2 block 1026 */
  2561. /* bit 6,7 block 3 block 1027 */
  2562. /* byte 1 bit 0,1 block 4 block 1028 */
  2563. /* bit 2,3 block 5 block 1029 */
  2564. /* bit 4,5 block 6 block 1030 */
  2565. /* bit 6,7 block 7 block 1031 */
  2566. /* and so on. The data is protected by EDC. */
  2567. /*----------------------------------------------------------------------*/
  2568. static FLStatus readBBT(FLFlash * flash, dword unitNo, dword unitsToRead,
  2569. byte blockMultiplier, byte FAR1 * buffer,
  2570. FLBoolean reconstruct)
  2571. {
  2572. register Sword i;
  2573. FLStatus status;
  2574. byte tmp;
  2575. dword addr;
  2576. Sdword bufPtr = unitsToRead - 1; /* Point to last byte of user buffer */
  2577. word bytesPerFloor;
  2578. byte firstBlocks;
  2579. byte smallBBT[8];
  2580. dword start;
  2581. dword last;
  2582. word length;
  2583. byte FAR1* tmpBuffer;
  2584. CardAddress floorInc; /* floor address incrementor */
  2585. word actualRead;
  2586. dword alignAddr;
  2587. word curRead; /* Number of bytes to read from this floor BBT */
  2588. /* Interleave-2 has 2 block entries for each combined block. This variable */
  2589. /* is used to shift the bbt size. 0 for int-1 1 for int-2 */
  2590. dword shift = (flash->interleaving - 1);
  2591. /* Arg sanity check */
  2592. if ((((unitNo + unitsToRead) << blockMultiplier) <<
  2593. flash->erasableBlockSizeBits) > (flash->noOfChips * flash->chipSize))
  2594. return flBadParameter; /* Too many blocks */
  2595. if (unitsToRead == 0) /* No blocks at all */
  2596. return flOK;
  2597. if(unitsToRead < 8) /* Algorithm does not fit */
  2598. {
  2599. status = readBBT(flash,unitNo,8,blockMultiplier,smallBBT,FALSE);
  2600. tffscpy(buffer,smallBBT,unitsToRead);
  2601. return status;
  2602. }
  2603. #ifndef MTD_STANDALONE
  2604. /* Force remapping of internal catched sector */
  2605. flash->socket->remapped = TRUE;
  2606. #endif /* MTD_STANDALONE */
  2607. bytesPerFloor = (word)(NFDC21thisVars->floorSize >>
  2608. flash->erasableBlockSizeBits) >>
  2609. ((flash->mediaType == MDOCP_TYPE) ? 1 : 2);
  2610. if(blockMultiplier == 0) /* 2 blocks per byte */
  2611. {
  2612. /* Calculate the first and last bytes of BBT to read. There area 4
  2613. interleave-1 blocks per byte, so interleave-2 has 4 blocks per 2
  2614. bytes */
  2615. start = ((unitNo >> 2)<<shift); /* in bytes */
  2616. last = (((unitNo+unitsToRead-1) >> 2)<<shift); /* in bytes */
  2617. length = (word)(last - start + flash->interleaving); /* in bytes */
  2618. tmpBuffer = buffer; /* bbt buffer pointer */
  2619. for (floorInc = (start / bytesPerFloor) * NFDC21thisVars->floorSize +
  2620. BBT_MEDIA_OFFSET, last = (dword) length,
  2621. start = start % bytesPerFloor; last > 0 ;
  2622. floorInc += NFDC21thisVars->floorSize)
  2623. {
  2624. curRead = (word)TFFSMIN(bytesPerFloor - start,last);
  2625. last -= curRead; /* bytes left to read */
  2626. alignAddr = (start >> SECTOR_SIZE_BITS)<<SECTOR_SIZE_BITS;
  2627. /* Not in Millennium plus but there might be 1024 BBT bytes
  2628. per floor */
  2629. for ( ;curRead > 0 ; alignAddr+=SECTOR_SIZE,start = 0)
  2630. {
  2631. if (doc2Read(flash,alignAddr + floorInc, NFDC21thisBuffer,
  2632. SECTOR_SIZE , EDC) != flOK)
  2633. {
  2634. DEBUG_PRINT(("Debug: Error reading DiskOnChip Millennium Plus BBT.\r\n"));
  2635. return flBadBBT;
  2636. }
  2637. actualRead = (word)TFFSMIN((word)(SECTOR_SIZE - start),curRead);
  2638. tffscpy(tmpBuffer,NFDC21thisBuffer + start, actualRead);
  2639. tmpBuffer = BYTE_ADD_FAR(tmpBuffer,actualRead); /* increament buffer */
  2640. curRead -= actualRead;
  2641. }
  2642. }
  2643. /* Convert last byte if only some of the blocks represented by it
  2644. are needed and if it is not the only byte read */
  2645. /* Save first the first byte - 1 for int-1 2 for int-2 */
  2646. if(shift)
  2647. {
  2648. firstBlocks = buffer[0] & buffer[1];
  2649. /* Convert last 2 bytes */
  2650. tmp = (*BYTE_ADD_FAR(buffer,length-1)) & /* lower lane */
  2651. (*BYTE_ADD_FAR(buffer,length-2)); /* higher lane */
  2652. }
  2653. else
  2654. {
  2655. firstBlocks = buffer[0];
  2656. /* Convert last bytes */
  2657. tmp = *BYTE_ADD_FAR(buffer,length-1);
  2658. }
  2659. switch ((unitNo+unitsToRead) & 3) /* Last block number byte offset */
  2660. {
  2661. case 3:
  2662. *BYTE_ADD_FAR(buffer,bufPtr) = tmp | 0xCF;
  2663. bufPtr--;
  2664. case 2:
  2665. *BYTE_ADD_FAR(buffer,bufPtr) = tmp | 0xF3;
  2666. bufPtr--;
  2667. case 1:
  2668. *BYTE_ADD_FAR(buffer,bufPtr) = tmp | 0xFC;
  2669. bufPtr--;
  2670. length -= 2; /* Point to last bbt byte */
  2671. default:
  2672. break;
  2673. }
  2674. /* Convert all aligned blocks */
  2675. while (bufPtr > flash->interleaving)
  2676. {
  2677. if(shift)
  2678. {
  2679. tmp = (*BYTE_ADD_FAR(buffer,length-1)) & /* lower lane */
  2680. (*BYTE_ADD_FAR(buffer,length-2)); /* higher lane */
  2681. }
  2682. else
  2683. {
  2684. tmp = *BYTE_ADD_FAR(buffer,length-1);
  2685. }
  2686. *BYTE_ADD_FAR(buffer,bufPtr ) = tmp | 0x3f;
  2687. *BYTE_ADD_FAR(buffer,bufPtr-1) = tmp | 0xcf;
  2688. *BYTE_ADD_FAR(buffer,bufPtr-2) = tmp | 0xf3;
  2689. *BYTE_ADD_FAR(buffer,bufPtr-3) = tmp | 0xfc;
  2690. bufPtr -= 4;
  2691. length -= flash->interleaving;
  2692. }
  2693. /* Convert first unaligned blocks (0,1,2) */
  2694. bufPtr=0;
  2695. switch(unitNo & 3)
  2696. {
  2697. case 1:
  2698. *BYTE_ADD_FAR(buffer,bufPtr) = firstBlocks | 0xF3;
  2699. bufPtr++;
  2700. case 2:
  2701. *BYTE_ADD_FAR(buffer,bufPtr) = firstBlocks | 0xCF;
  2702. bufPtr++;
  2703. case 3:
  2704. *BYTE_ADD_FAR(buffer,bufPtr) = firstBlocks | 0x3F;
  2705. default:
  2706. break;
  2707. }
  2708. /* Mark all bad blocks with 0 */
  2709. for (bufPtr=0;bufPtr<(Sdword)unitsToRead;bufPtr++)
  2710. {
  2711. if (*BYTE_ADD_FAR(buffer,bufPtr) != BBT_GOOD_UNIT)
  2712. {
  2713. *BYTE_ADD_FAR(buffer,bufPtr) = 0;
  2714. }
  2715. }
  2716. /* Add OTP and 2 DPS for all floors */
  2717. for (tmp=0,addr=0;tmp<flash->noOfFloors;tmp++,addr=tmp<<10)
  2718. {
  2719. for (i=0;i<((shift) ? 3 : 5);i++) /* reserved units */
  2720. if ((addr+i >= unitNo)&&(addr+i <= unitNo+unitsToRead))
  2721. *BYTE_ADD_FAR(buffer,addr+i-unitNo) = BBT_UNAVAIL_UNIT;
  2722. }
  2723. }
  2724. else /* several blocks per unit */
  2725. {
  2726. return flBadBBT;
  2727. }
  2728. return flOK;
  2729. }
  2730. #endif /* MTD_READ_BBT */
  2731. /*----------------------------------------------------------------------*/
  2732. /* c h a n g e I n t e r l e a v e */
  2733. /* */
  2734. /* Change to new interleave mode. */
  2735. /* */
  2736. /* Note : DiskOnChip Millennium Plus 16MB always reports flOK */
  2737. /* */
  2738. /* Parameters: */
  2739. /* flash : Pointer identifying drive. */
  2740. /* interNum : New interleave factor. */
  2741. /* */
  2742. /* Note - Devices that were HW configured to interleave 1 can not */
  2743. /* change to interleave - 2. */
  2744. /* Note - Global variables changed: */
  2745. /* flash->interleaving */
  2746. /* NFDC21thisVars->pageAreaSize */
  2747. /* flash->pageSize */
  2748. /* NFDC21thisVars->tailSize */
  2749. /* NFDC21thisVars->pageMask */
  2750. /* flash->erasableBlockSize */
  2751. /* NFDC21thisVars->noOfBlocks */
  2752. /* */
  2753. /* Returns: */
  2754. /* flOK on success, otherwise flInterlreavError. */
  2755. /*----------------------------------------------------------------------*/
  2756. FLStatus changeInterleave(FLFlash * flash, byte interNum)
  2757. {
  2758. Reg8bitType prevInterleaveReg;
  2759. if(setDOCPlusBusType(flash,flBusConfig[flSocketNoOf(flash->socket)],
  2760. interNum,NFDC21thisVars->if_cfg) == FALSE)
  2761. return flGeneralFailure;
  2762. if(flash->mediaType == MDOCP_TYPE) /* DiskOnChip Millennium Plus 32MB */
  2763. {
  2764. /* Save current configuration */
  2765. prevInterleaveReg = flRead8bitRegPlus(flash,NconfigInput);
  2766. /* check if we need to change interleave */
  2767. if ((prevInterleaveReg & CONFIG_INTLV_MASK) == ((interNum-1)<<2))
  2768. return flOK;
  2769. if(interNum == 1)
  2770. {
  2771. flWrite8bitRegPlus(flash,NconfigInput,(byte)(prevInterleaveReg & ~CONFIG_INTLV_MASK)); /* interleave 1 */
  2772. if((flRead8bitRegPlus(flash,NconfigInput) & CONFIG_INTLV_MASK) != 0)
  2773. return(flInterleaveError); /* could not change interleave */
  2774. }
  2775. else
  2776. {
  2777. flWrite8bitRegPlus(flash,NconfigInput,(byte)(prevInterleaveReg | CONFIG_INTLV_MASK)); /* interleave 2 */
  2778. if((flRead8bitRegPlus(flash,NconfigInput) & CONFIG_INTLV_MASK) != CONFIG_INTLV_MASK)
  2779. return(flInterleaveError); /* could not change interleave */
  2780. }
  2781. }
  2782. else
  2783. {
  2784. interNum = 1;
  2785. }
  2786. /* change structure elements values */
  2787. flash->interleaving = interNum-1 ;
  2788. NFDC21thisVars->pageAreaSize = 0x100 << flash->interleaving;
  2789. flash->pageSize = 0X200 << flash->interleaving;
  2790. NFDC21thisVars->tailSize = EXTRA_LEN << flash->interleaving; /* 8 in interleave-1, 16 in interleave-2 */
  2791. NFDC21thisVars->pageMask = (unsigned short)(flash->pageSize - 1);
  2792. flash->erasableBlockSize = NFDC21thisVars->pagesPerBlock * flash->pageSize;
  2793. NFDC21thisVars->noOfBlocks = (unsigned short)( flash->chipSize / flash->erasableBlockSize );
  2794. flash->interleaving++;
  2795. for(flash->erasableBlockSizeBits = 0 ;
  2796. (1UL << flash->erasableBlockSizeBits) < flash->erasableBlockSize;
  2797. flash->erasableBlockSizeBits++);
  2798. return(flOK);
  2799. }
  2800. #if (!defined(NO_IPL_CODE) && defined (HW_PROTECTION))
  2801. /*----------------------------------------------------------------------*/
  2802. /* r e a d I P L */
  2803. /* */
  2804. /* Find a good copy of the IPL and read it to user buffer. */
  2805. /* */
  2806. /* Parameters: */
  2807. /* vol : Pointer identifying drive. */
  2808. /* buffer : buffer to read to. */
  2809. /* length : number of bytes to read. */
  2810. /* */
  2811. /* Note - Length must be an integer number of 512 bytes. */
  2812. /* */
  2813. /* Returns: */
  2814. /* flOK on success, none zero otherwise. */
  2815. /*----------------------------------------------------------------------*/
  2816. static FLStatus readIPL(FLFlash * flash, void FAR1 * buffer, word length)
  2817. {
  2818. byte FAR1 * bufPtr = (byte FAR1 *)buffer;
  2819. const void FAR0* winPtr = (const void FAR1*)flash->win;
  2820. word tmpLength = 0;
  2821. int i;
  2822. volatile byte prevMaxId;
  2823. /* IPL must be read using full 512 bytes sector */
  2824. if ((length % SECTOR_SIZE != 0)&&(length > flash->noOfFloors*IPL_MAX_SIZE))
  2825. return flBadLength;
  2826. /* Force IPL to be loaded */
  2827. checkStatus(forceDownLoad(flash));
  2828. /* Force NORMAL mode */
  2829. checkStatus(chkASICmode(flash));
  2830. if(flash->win == NULL)
  2831. return flGeneralFailure;
  2832. /* Store max ID and open IPL of high floors */
  2833. prevMaxId = setIplSize(flash, flash->noOfFloors);
  2834. for(i = 0 ; length > 0 ; length -= tmpLength,i++)
  2835. {
  2836. tmpLength = TFFSMIN(length,IPL_MAX_SIZE);
  2837. tffscpy(bufPtr , (void FAR1*)winPtr , tmpLength);
  2838. bufPtr = BYTE_ADD_FAR(bufPtr,tmpLength);
  2839. switch(i)
  2840. {
  2841. case 1:
  2842. winPtr = BYTE_ADD_FAR(winPtr,5*IPL_MAX_SIZE);
  2843. break;
  2844. case 0:
  2845. case 2:
  2846. winPtr = BYTE_ADD_FAR(winPtr,IPL_MAX_SIZE);
  2847. default:
  2848. break;
  2849. }
  2850. }
  2851. /* Restore MAX id */
  2852. prevMaxId = setIplSize(flash, prevMaxId);
  2853. return flOK;
  2854. }
  2855. #ifndef FL_READ_ONLY
  2856. /*----------------------------------------------------------------------*/
  2857. /* w r i t e I P L */
  2858. /* */
  2859. /* Write new IPL. */
  2860. /* */
  2861. /* Note : When write operation starts from the middle of the IPL, it */
  2862. /* not erase the previous content. Therefore you should use the */
  2863. /* use offset != 0 only after an operation that did start from 0.*/
  2864. /* */
  2865. /* Note : Offset parameter is given in sector (512 bytes). */
  2866. /* */
  2867. /* Parameters: */
  2868. /* flash : Pointer identifying drive. */
  2869. /* buffer : buffer to write from. */
  2870. /* length : number of bytes to write. */
  2871. /* offset : sector number to start from. */
  2872. /* flags : Modes to write IPL : */
  2873. /* FL_IPL_MODE_NORMAL - Normal mode. */
  2874. /* FL_IPL_DOWNLOAD - Download new IPL when done */
  2875. /* FL_IPL_MODE_SA - Strong Arm IPL mode */
  2876. /* FL_IPL_MODE_XSCALE - X-Scale IPL mode */
  2877. /* */
  2878. /* Returns: */
  2879. /* flOK on success, none zero otherwise. */
  2880. /*----------------------------------------------------------------------*/
  2881. static FLStatus writeIPL(FLFlash * flash, const void FAR1 * buffer,
  2882. word length,byte offset, unsigned flags)
  2883. {
  2884. FLBoolean restoreInterleave = FALSE;
  2885. FLStatus status;
  2886. FLStatus secondStatus;
  2887. int i;
  2888. byte FAR1 * tmpPtr = (byte FAR0 *)buffer;
  2889. byte dps[NO_OF_DPS][SIZE_OF_DPS];
  2890. CardAddress iplOffset[4];
  2891. byte floor;
  2892. byte downloadStatus;
  2893. dword floorInc;
  2894. word curWrite;
  2895. word redundantUnit; /* First unit to erase - might have bad data */
  2896. word goodUnit; /* Second unit to erase - has valid DPS */
  2897. dword goodDPS; /* Where to read DPS - in second unit */
  2898. dword redundantDPS; /* Where to write DPS - in first unit */
  2899. dword dps1Copy0; /* Offset to DPS1 copy 0 */
  2900. word dps1UnitNo; /* Offset to redundant DPS unit */
  2901. dword copyOffset; /* Offset to redundant units */
  2902. unsigned iplModeFlags; /* IPL Strong Arm and\or XScale mode flags. */
  2903. /* Check IPL requested size against the real IPL size */
  2904. if (length + (offset<<SECTOR_SIZE_BITS) > flash->noOfFloors*IPL_MAX_SIZE)
  2905. return flBadLength;
  2906. /* Check mode of ASIC and set to NORMAL.*/
  2907. status = chkASICmode(flash);
  2908. if(status != flOK)
  2909. return status;
  2910. /* Check IPL mode flags */
  2911. iplModeFlags = flags & (FL_IPL_MODE_SA|FL_IPL_MODE_XSCALE);
  2912. if(iplModeFlags) /* Write MODE mark */
  2913. {
  2914. if(iplModeFlags == (FL_IPL_MODE_SA|FL_IPL_MODE_XSCALE))
  2915. {
  2916. DEBUG_PRINT(("ERROR - Can write IPL with both Strong Arm and X-Scale modes\r\n"));
  2917. return flBadParameter;
  2918. }
  2919. if(flash->mediaType == MDOCP_TYPE) /* DiskOnChip Millennium Plus 32MB */
  2920. {
  2921. DEBUG_PRINT(("ERROR - DiskOnChip Millennium Plus 32MB does not support special IPL modes\r\n"));
  2922. return flFeatureNotSupported;
  2923. }
  2924. }
  2925. /* Send default key for unprotected partitions */
  2926. if (flash->protectionKeyInsert != NULL)
  2927. {
  2928. status = flash->protectionKeyInsert(flash,1, (byte *)DEFAULT_KEY);
  2929. if(status != flOK)
  2930. return status;
  2931. }
  2932. /* make sure to be in interleave 1 mode */
  2933. if (flash->interleaving==2) /* store previous */
  2934. {
  2935. restoreInterleave = TRUE;
  2936. status = changeInterleave(flash, 1); /* change to interleave 1. abort if failed */
  2937. if(status != flOK)
  2938. return status;
  2939. }
  2940. #ifndef MTD_STANDALONE
  2941. /* Force remapping of internal catched sector */
  2942. flash->socket->remapped = TRUE;
  2943. #endif /* MTD_STANDALONE */
  2944. if(flash->mediaType == MDOCP_TYPE) /* DiskOnChip Millennium Plus 32MB */
  2945. {
  2946. copyOffset = flash->chipSize>>1; /* The chips are consequtive */
  2947. dps1UnitNo = DPS1_UNIT_NO_32;
  2948. dps1Copy0 = DPS1_COPY0_32;
  2949. iplOffset[0] = IPL0_COPY0_32;
  2950. iplOffset[2] = IPL1_COPY0_32;
  2951. }
  2952. else /* DiskOnChip Millennium Plus 16MB */
  2953. {
  2954. /* DPS0 / DPS1 / DPS0 copy / DPS 1 copy */
  2955. copyOffset = flash->erasableBlockSize;
  2956. dps1UnitNo = DPS1_UNIT_NO_16;
  2957. dps1Copy0 = DPS1_COPY0_16;
  2958. iplOffset[0] = IPL0_COPY0_16;
  2959. iplOffset[2] = IPL1_COPY0_16;
  2960. }
  2961. iplOffset[1] = iplOffset[0]+SECTOR_SIZE;
  2962. iplOffset[3] = iplOffset[2]+SECTOR_SIZE;
  2963. floor = offset >> 1; /* Skip to proper floor (2 * 512 per floor) */
  2964. offset -= floor << 1; /* Update offset */
  2965. /* Reading IPL starting from 1k of floor 0 and up */
  2966. for (floorInc=floor * NFDC21thisVars->floorSize;
  2967. (floor<flash->noOfFloors)&&(length>0);
  2968. floor++,floorInc+=NFDC21thisVars->floorSize)
  2969. {
  2970. setFloor(flash,floor); /* Set the floor to use */
  2971. /* Prepare inernal write buffer */
  2972. /* Note - buffer and NFDC21thisBuffer might be the same buffer */
  2973. curWrite = (word)TFFSMIN(length,SECTOR_SIZE);
  2974. tffscpy(NFDC21thisBuffer,(void *)tmpPtr,curWrite);
  2975. tffsset(NFDC21thisBuffer+curWrite,0xff,SECTOR_SIZE-curWrite);
  2976. /* When starting from the second sector do not erase the units */
  2977. if (offset != 0)
  2978. {
  2979. status = doc2Write(flash,iplOffset[2]+floorInc,NFDC21thisBuffer,SECTOR_SIZE,EDC);
  2980. if(status!=flOK) goto END_WRITE_IPL;
  2981. status = doc2Write(flash,iplOffset[2]+SECTOR_SIZE+floorInc,NFDC21thisBuffer,SECTOR_SIZE,EDC);
  2982. if(status!=flOK) goto END_WRITE_IPL;
  2983. status = doc2Write(flash,iplOffset[2]+copyOffset+floorInc,NFDC21thisBuffer,SECTOR_SIZE,EDC);
  2984. if(status!=flOK) goto END_WRITE_IPL;
  2985. status = doc2Write(flash,iplOffset[2]+SECTOR_SIZE+copyOffset+floorInc,NFDC21thisBuffer,SECTOR_SIZE,EDC);
  2986. if(status!=flOK) goto END_WRITE_IPL;
  2987. offset = 0;
  2988. goto WRITE_IPL_NEXT_FLOOR;
  2989. }
  2990. /* Decide which copy to use acording to the previous download */
  2991. downloadStatus = flRead8bitRegPlus(flash,NdownloadStatus);
  2992. switch (downloadStatus & DWN_STAT_DPS1_ERR)
  2993. {
  2994. case DWN_STAT_DPS1_ERR: /* Both copies are invalid */
  2995. status = flBadDownload;
  2996. goto END_WRITE_IPL;
  2997. case DWN_STAT_DPS10_ERR: /* First copy is bad */
  2998. if(flash->mediaType == MDOCP_TYPE)
  2999. {
  3000. redundantUnit = (word)(dps1UnitNo + floor*(NFDC21thisVars->floorSize>>flash->erasableBlockSizeBits));
  3001. goodUnit = (word)(redundantUnit + (copyOffset>>flash->erasableBlockSizeBits));
  3002. redundantDPS = dps1Copy0 + floorInc;
  3003. goodDPS = redundantDPS + copyOffset;
  3004. }
  3005. else
  3006. {
  3007. redundantUnit = (word)(dps1UnitNo + floor*(NFDC21thisVars->floorSize>>flash->erasableBlockSizeBits));
  3008. goodUnit = (word)(redundantUnit + (copyOffset>>flash->erasableBlockSizeBits));
  3009. redundantDPS = dps1Copy0 + floorInc;
  3010. goodDPS = redundantDPS + copyOffset;
  3011. }
  3012. break;
  3013. default: /* Both copies are good */
  3014. goodUnit = (word)(dps1UnitNo + floor*(NFDC21thisVars->floorSize>>flash->erasableBlockSizeBits));
  3015. redundantUnit = (word)(goodUnit + (copyOffset>>flash->erasableBlockSizeBits));
  3016. goodDPS = dps1Copy0 + floorInc;
  3017. redundantDPS = goodDPS + copyOffset;
  3018. }
  3019. /* Read previous dps */
  3020. status = doc2Read(flash,goodDPS,&(dps[0][0]),SIZE_OF_DPS,0);
  3021. if(status!=flOK) goto END_WRITE_IPL;
  3022. status = doc2Read(flash,goodDPS + REDUNDANT_DPS_OFFSET,
  3023. &(dps[1][0]),SIZE_OF_DPS,0);
  3024. if(status!=flOK) goto END_WRITE_IPL;
  3025. /* Erase the other unit - not the one we downloaded from */
  3026. status = flash->erase(flash,redundantUnit,1);
  3027. if(status!=flOK) goto END_WRITE_IPL;
  3028. /* Write DPS */
  3029. status = doc2Write(flash,redundantDPS,&(dps[0][0]),SIZE_OF_DPS,0);
  3030. if(status!=flOK) goto END_WRITE_IPL;
  3031. status = doc2Write(flash,redundantDPS + REDUNDANT_DPS_OFFSET,
  3032. &(dps[1][0]),SIZE_OF_DPS,0);
  3033. if(status!=flOK) goto END_WRITE_IPL;
  3034. /* Erase the unit that we downloaded from */
  3035. status = flash->erase(flash,goodUnit,1);
  3036. if(status!=flOK) goto END_WRITE_IPL;
  3037. /* Write DPS */
  3038. status = doc2Write(flash,goodDPS, &(dps[0][0]),SIZE_OF_DPS,0);
  3039. if(status!=flOK) goto END_WRITE_IPL;
  3040. status = doc2Write(flash,goodDPS + REDUNDANT_DPS_OFFSET,
  3041. &(dps[1][0]),SIZE_OF_DPS,0);
  3042. /* Write IPL - 2 copies of first unit */
  3043. for(i=0;i<2;i++)
  3044. {
  3045. status = doc2Write(flash,iplOffset[i]+floorInc,NFDC21thisBuffer,SECTOR_SIZE,EDC);
  3046. if(status!=flOK) goto END_WRITE_IPL;
  3047. status = doc2Write(flash,iplOffset[i]+floorInc+copyOffset,NFDC21thisBuffer,SECTOR_SIZE,EDC);
  3048. if(status!=flOK) goto END_WRITE_IPL;
  3049. }
  3050. /* Write next 512 bytes of IPL if needed */
  3051. length -= curWrite;
  3052. if (length > 0)
  3053. {
  3054. /* Prepare next buffer */
  3055. tmpPtr = BYTE_ADD_FAR(tmpPtr,SECTOR_SIZE);
  3056. curWrite = (word)TFFSMIN(length,SECTOR_SIZE);
  3057. tffscpy(NFDC21thisBuffer,tmpPtr,curWrite);
  3058. tffsset(NFDC21thisBuffer+curWrite,0x0,SECTOR_SIZE-curWrite);
  3059. for(;i<4;i++)
  3060. {
  3061. status = doc2Write(flash,iplOffset[i]+floorInc,NFDC21thisBuffer,SECTOR_SIZE,EDC);
  3062. if(status!=flOK) goto END_WRITE_IPL;
  3063. status = doc2Write(flash,iplOffset[i]+floorInc+copyOffset,NFDC21thisBuffer,SECTOR_SIZE,EDC);
  3064. if(status!=flOK) goto END_WRITE_IPL;
  3065. }
  3066. }
  3067. WRITE_IPL_NEXT_FLOOR:
  3068. length -= curWrite;
  3069. if(length>0)
  3070. tmpPtr = BYTE_ADD_FAR(tmpPtr,SECTOR_SIZE);
  3071. if(iplModeFlags) /* Write MODE mark */
  3072. {
  3073. byte mark = IPL_SA_MODE_MARK; /* Strong arm is the default */
  3074. if(flags & FL_IPL_MODE_XSCALE) /* Unless X-Scale wase asked for */
  3075. mark = IPL_XSCALE_MODE_MARK;
  3076. status = doc2Write(flash,IPL_MODE_MARK_OFFSET+floorInc,&mark,1,EXTRA);
  3077. if(status!=flOK) goto END_WRITE_IPL;
  3078. }
  3079. } /* End for loop over floors */
  3080. END_WRITE_IPL:
  3081. if ( restoreInterleave == TRUE)
  3082. {
  3083. chkASICmode(flash); /* Release posible access error */
  3084. secondStatus = changeInterleave(flash, 2); /* change to interleave 2. */
  3085. if(secondStatus != flOK)
  3086. return secondStatus;
  3087. }
  3088. if(status == flOK)
  3089. {
  3090. if((flags & FL_IPL_DOWNLOAD) == 0)
  3091. return flOK;
  3092. if(flash->download != NULL)
  3093. return flash->download(flash);
  3094. DFORMAT_PRINT(("ERROR - IPL was not downloaded since MTD does not support the feature\r\n"));
  3095. }
  3096. return status;
  3097. }
  3098. #endif /* FL_READ_ONLY */
  3099. #endif /* not NO_IPL_CODE & HW_PROTECTION */
  3100. #ifdef HW_OTP
  3101. #ifndef FL_READ_ONLY
  3102. /*----------------------------------------------------------------------*/
  3103. /* w r i t e O T P */
  3104. /* */
  3105. /* Write and lock the customer OTP. */
  3106. /* */
  3107. /* Parameters: */
  3108. /* flash : Pointer identifying drive. */
  3109. /* buffer : buffer to write from. */
  3110. /* length : number of bytes to write. */
  3111. /* */
  3112. /* Note - customer OTP memory structure: (flash pages 6-31 */
  3113. /* byte 0 - Indicates the lock state (0 for locked). */
  3114. /* bytes 3-7 - OTP used size. */
  3115. /* page 7-19 - 6K of the unit - customer data. */
  3116. /* */
  3117. /* Returns: */
  3118. /* flOK on success, none zero otherwise. */
  3119. /*----------------------------------------------------------------------*/
  3120. static FLStatus writeOTP(FLFlash * flash , const void FAR1 * buffer, word length)
  3121. {
  3122. word lastSectorSize = (word)(length % SECTOR_SIZE);
  3123. OTPLockStruct lock;
  3124. FLStatus status;
  3125. int shift = flash->interleaving-1;
  3126. selectFloor(flash,0);
  3127. /* Check mode of ASIC and set to NORMAL.*/
  3128. status = chkASICmode(flash);
  3129. if(status != flOK)
  3130. return status;
  3131. if (length > CUSTOMER_OTP_SIZE)
  3132. return flBadLength;
  3133. /* write the data with EDC */
  3134. status = doc2Write(flash, (CUSTOMER_OTP_START<<shift)+flash->pageSize, buffer,
  3135. length-lastSectorSize, EDC);
  3136. if(status != flOK)
  3137. return status;
  3138. /* Write last partial sector */
  3139. if (lastSectorSize > 0)
  3140. {
  3141. /* Force remapping of internal catched sector */
  3142. #ifndef MTD_STANDALONE
  3143. flash->socket->remapped = TRUE;
  3144. #endif /* MTD_STANDALONE */
  3145. tffsset(NFDC21thisBuffer,0,sizeof(NFDC21thisBuffer));
  3146. tffscpy(NFDC21thisBuffer,BYTE_ADD_FAR(buffer,length-lastSectorSize),lastSectorSize);
  3147. status = doc2Write(flash, (CUSTOMER_OTP_START<<shift) + flash->pageSize +
  3148. length-lastSectorSize, NFDC21thisBuffer, SECTOR_SIZE, EDC);
  3149. if(status != flOK)
  3150. return status;
  3151. }
  3152. /* Lock area */
  3153. tffsset((void FAR1 *)&lock,0,sizeof(lock));
  3154. lock.lockByte[0] = OTP_LOCK_MARK;
  3155. toLE4(lock.usedSize,(dword)length); /* store size of data */
  3156. status = doc2Write(flash, (CUSTOMER_OTP_START<<shift), &lock, sizeof(lock), 0);
  3157. if(status == flOK)
  3158. status = forceDownLoad(flash);
  3159. return status;
  3160. }
  3161. #endif /* FL_READ_ONLY */
  3162. /*----------------------------------------------------------------------*/
  3163. /* o t p S i z e */
  3164. /* */
  3165. /* Returns the size and state of the OTP area. */
  3166. /* */
  3167. /* Parameters: */
  3168. /* flash : Pointer identifying drive. */
  3169. /* sectionSize : Total OTP size. */
  3170. /* usedSize : Used OTP size. */
  3171. /* locked : Lock state (LOCKED_OTP for locked). */
  3172. /* */
  3173. /* Returns: */
  3174. /* flOK on success, none zero otherwise. */
  3175. /*----------------------------------------------------------------------*/
  3176. static FLStatus otpSize(FLFlash * flash, dword FAR2* sectionSize,
  3177. dword FAR2* usedSize, word FAR2* locked)
  3178. {
  3179. OTPLockStruct lock;
  3180. FLStatus status = flOK;
  3181. int shift = flash->interleaving-1;
  3182. selectFloor(flash,0);
  3183. if (flRead8bitRegPlus(flash,NprotectionStatus) & PROTECT_STAT_COTPL_MASK)
  3184. {
  3185. status = doc2Read(flash,(CUSTOMER_OTP_START<<shift) , &lock, sizeof(lock), 0);
  3186. *usedSize = LE4(lock.usedSize);
  3187. *locked = LOCKED_OTP;
  3188. }
  3189. else
  3190. {
  3191. *locked = 0;
  3192. *usedSize = 0;
  3193. }
  3194. /* return the maximum capacity available */
  3195. *sectionSize = CUSTOMER_OTP_SIZE;
  3196. return status;
  3197. }
  3198. /*----------------------------------------------------------------------*/
  3199. /* r e a d O T P */
  3200. /* */
  3201. /* Read data from the customer OTP. */
  3202. /* */
  3203. /* Parameters: */
  3204. /* flash : Pointer identifying drive. */
  3205. /* offset : Offset from the beginning of OTP area to read from. */
  3206. /* buffer : buffer to read into. */
  3207. /* length : number of bytes to read. */
  3208. /* */
  3209. /* Returns: */
  3210. /* flOK on success, none zero otherwise. */
  3211. /*----------------------------------------------------------------------*/
  3212. static FLStatus readOTP(FLFlash * flash, word offset, void FAR1 * buffer, word length)
  3213. {
  3214. dword usedSize;
  3215. dword tmp;
  3216. word locked;
  3217. FLStatus status;
  3218. CardAddress otpStartAddr,startReadAddr,endReadAddr,remainder;
  3219. byte FAR1* bufPtr = (byte FAR1*) buffer;
  3220. int shift = flash->interleaving-1;
  3221. selectFloor(flash,0);
  3222. /* Check mode of ASIC and set to NORMAL.*/
  3223. status = chkASICmode(flash);
  3224. /* Check otp area written size */
  3225. if(status==flOK)
  3226. status = otpSize(flash,&tmp,&usedSize,&locked);
  3227. if(status != flOK)
  3228. return status;
  3229. if (locked != LOCKED_OTP)
  3230. return flNoSpaceInVolume; /* Area not locked */
  3231. if ((dword)(offset+length) > usedSize)
  3232. return flBadLength; /* Exceeds used space */
  3233. #ifndef MTD_STANDALONE
  3234. /* Force remapping of internal catched sector */
  3235. flash->socket->remapped = TRUE;
  3236. #endif /* MTD_STANDALONE */
  3237. /**************************/
  3238. /* read the data with EDC */
  3239. /**************************/
  3240. otpStartAddr = (CUSTOMER_OTP_START<<shift) + flash->pageSize;
  3241. /* tmp - OTP offset rounded down to sectors */
  3242. tmp = (dword)((offset >> SECTOR_SIZE_BITS) << SECTOR_SIZE_BITS);
  3243. /* startReadAddr - Physical address of first sector to read */
  3244. startReadAddr = otpStartAddr + tmp;
  3245. /* remainder - size of last partial sector to read */
  3246. remainder = (offset+length) % SECTOR_SIZE;
  3247. /* endReadAddr - Physical address of the last OTP sector to be read */
  3248. endReadAddr = otpStartAddr + offset + length - remainder;
  3249. if (tmp != offset) /* Start at unaligned address */
  3250. {
  3251. checkStatus(doc2Read(flash, startReadAddr, NFDC21thisBuffer, SECTOR_SIZE, EDC));
  3252. usedSize = TFFSMIN(SECTOR_SIZE + tmp - offset,length);
  3253. tffscpy(bufPtr,NFDC21thisBuffer + offset - tmp,(word)usedSize);
  3254. bufPtr = BYTE_ADD_FAR(bufPtr,usedSize);
  3255. startReadAddr += usedSize;
  3256. length -= (word)usedSize;
  3257. }
  3258. /* Start at aligned address */
  3259. if(length > 0)
  3260. {
  3261. checkStatus(doc2Read(flash, startReadAddr, bufPtr,
  3262. endReadAddr-startReadAddr , EDC));
  3263. /* Read last sector partial page */
  3264. if(remainder)
  3265. {
  3266. bufPtr = BYTE_ADD_FAR(bufPtr,endReadAddr-startReadAddr);
  3267. checkStatus(doc2Read(flash, endReadAddr, NFDC21thisBuffer, SECTOR_SIZE, EDC));
  3268. tffscpy(bufPtr,NFDC21thisBuffer,remainder);
  3269. }
  3270. }
  3271. return flOK;
  3272. }
  3273. /*----------------------------------------------------------------------*/
  3274. /* g e t U n i q u e I d */
  3275. /* */
  3276. /* Retreave the device 16 bytes unique ID. */
  3277. /* */
  3278. /* Parameters: */
  3279. /* flash : Pointer identifying drive. */
  3280. /* buffer : buffer to read into. */
  3281. /* */
  3282. /* Returns: */
  3283. /* flOK on success, none zero otherwise. */
  3284. /*----------------------------------------------------------------------*/
  3285. static FLStatus getUniqueId(FLFlash * flash,void FAR1 * buffer)
  3286. {
  3287. /* Make sure contorller is set to NORMAL. */
  3288. FLStatus status = chkASICmode(flash);
  3289. if(status != flOK)
  3290. return status;
  3291. #ifndef MTD_STANDALONE
  3292. /* Force remapping of internal catched sector */
  3293. flash->socket->remapped = TRUE;
  3294. #endif /* MTD_STANDALONE */
  3295. /* read unit 0 sector 0 with ecc */
  3296. checkStatus(doc2Read(flash, 0 , NFDC21thisBuffer, SECTOR_SIZE, EDC));
  3297. /* copy relevant unique ID from 512 bytes buffer to user buffer */
  3298. tffscpy(buffer ,
  3299. NFDC21thisBuffer+(UNIQUE_ID_OFFSET << (flash->interleaving - 1)) ,
  3300. UNIQUE_ID_SIZE);
  3301. return flOK;
  3302. }
  3303. #endif /* HW_OTP */
  3304. /*----------------------------------------------------------------------*/
  3305. /* d o c P l u s I d e n t i f y */
  3306. /* */
  3307. /* Identify flash. This routine will be registered as the */
  3308. /* identification routine for this MTD. */
  3309. /* */
  3310. /* Parameters: */
  3311. /* flash : Pointer identifying drive */
  3312. /* */
  3313. /* Returns: */
  3314. /* FLStatus : 0 on success, otherwise failed. */
  3315. /*----------------------------------------------------------------------*/
  3316. FLStatus docPlusIdentify(FLFlash * flash)
  3317. {
  3318. FLStatus status;
  3319. int maxDevs, dev;
  3320. byte floor;
  3321. #ifdef NT5PORT
  3322. byte socketNo = (byte)flSocketNoOf(flash->socket);
  3323. #else
  3324. byte socketNo = flSocketNoOf(flash->socket);
  3325. #endif NT5PORT
  3326. DEBUG_PRINT(("Debug: entering NFDC MDOCP identification routine.\r\n"));
  3327. flash->mtdVars = &docMtdVars[socketNo];
  3328. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASE))
  3329. /* Get pointer to read back buffer */
  3330. NFDC21thisVars->readBackBuffer = flReadBackBufferOf(socketNo);
  3331. #endif /* VERIFY_WRITE || VERIFY_ERASE */
  3332. #ifndef MTD_STANDALONE
  3333. /* get pointer to buffer (we assume SINGLE_BUFFER is not defined) */
  3334. NFDC21thisVars->buffer = flBufferOf(socketNo);
  3335. flSetWindowBusWidth(flash->socket, 16);/* use 16-bits */
  3336. flSetWindowSpeed(flash->socket, 120); /* 120 nsec. */
  3337. #else
  3338. #if (defined (HW_PROTECTION) || defined (HW_OTP) || !defined (NO_IPL_CODE) || defined (MTD_READ_BBT))
  3339. NFDC21thisVars->buffer = &globalMTDBuffer;
  3340. #endif /* HW_PROTECTION || HW_OTP || !NO_IPL_CODE || MTD_READ_BBT */
  3341. #endif /* MTD_STANDALONE */
  3342. /* detect card - identify bit toggles on consequitive reads */
  3343. NFDC21thisWin = (NDOC2window)flMap(flash->socket, 0);
  3344. flash->win = NFDC21thisWin;
  3345. if (NFDC21thisWin == NULL)
  3346. return flUnknownMedia;
  3347. #ifndef FL_NO_USE_FUNC
  3348. /* Set default access routines */
  3349. if(setDOCPlusBusType(flash,flBusConfig[socketNo],1,
  3350. chooseDefaultIF_CFG(flBusConfig[socketNo])) == FALSE)
  3351. return flUnknownMedia;
  3352. #endif /* FL_NO_USE_FUNC */
  3353. /* Change controller to normal mode */
  3354. status = setASICmode (flash, DOC_CNTRL_MODE_NORMAL);
  3355. if(status != flOK)
  3356. return status;
  3357. #ifndef FL_NO_USE_FUNC
  3358. /* Set permenant access routines accoring to if_cfg and interleave */
  3359. if(setDOCPlusBusType(flash,flBusConfig[socketNo],
  3360. chkInterleave(flash),chkIF_CFG(flash)) == FALSE)
  3361. return flUnknownMedia;
  3362. #endif /* FL_NO_USE_FUNC */
  3363. dev = getControllerID(flash); /* Read chip ID */
  3364. switch (dev)
  3365. {
  3366. case CHIP_ID_MDOCP: /* Millennium Plus 32MB */
  3367. flash->chipSize = CHIP_TOTAL_SIZE<<1;
  3368. flash->mediaType = MDOCP_TYPE;
  3369. flash->changeableProtectedAreas = 1;
  3370. NFDC21thisVars->floorSizeBits = 25;
  3371. flash->firstUsableBlock = 3;
  3372. break;
  3373. case CHIP_ID_MDOCP16: /* Millennium Plus 16MB */
  3374. flash->chipSize = CHIP_TOTAL_SIZE;
  3375. flash->mediaType = MDOCP_16_TYPE;
  3376. flash->changeableProtectedAreas = 2;
  3377. NFDC21thisVars->floorSizeBits = 24;
  3378. flash->firstUsableBlock = 5;
  3379. break;
  3380. default:
  3381. DEBUG_PRINT(("Debug: failed to identify NFDC MDOCP.\r\n"));
  3382. return( flUnknownMedia );
  3383. }
  3384. NFDC21thisVars->win_io = NIPLpart2; /* NFDC21thisIO */
  3385. /* select flash device. change the address according floor!! */
  3386. setFloor (flash, 0); /* Map window to selected controler. */
  3387. selectChip (flash, MPLUS_SEL_CE|MPLUS_SEL_WP); /* Map window to selected flash device.*/
  3388. if (checkToggle(flash) == FALSE)
  3389. {
  3390. DEBUG_PRINT(("Debug: failed to identify NFDC MDOCP.\r\n"));
  3391. return( flUnknownMedia );
  3392. }
  3393. /* find the interleave value */
  3394. flash->interleaving = chkInterleave(flash);
  3395. /* reset all flash devices */
  3396. maxDevs = MAX_FLASH_DEVICES_MDOCP;
  3397. for ( floor = 0 ;floor < MAX_FLOORS ;floor++)
  3398. {
  3399. /* select floor */
  3400. setFloor(flash,floor);
  3401. /* select device */
  3402. for ( dev = 0 ; dev < maxDevs ; dev++ )
  3403. {
  3404. selectChip(flash, MPLUS_SEL_CE|MPLUS_SEL_WP );
  3405. command(flash, RESET_FLASH);
  3406. }
  3407. }
  3408. /* Set MDOCP flash parameters */
  3409. NFDC21thisVars->vendorID = 0x98; /* remember for next chips */
  3410. NFDC21thisVars->chipID = 0x75;
  3411. flash->type = TC58256_FLASH;
  3412. NFDC21thisVars->pagesPerBlock = MDOCP_PAGES_PER_BLOCK;
  3413. NFDC21thisVars->floorSize = flash->chipSize;
  3414. NFDC21thisVars->pageAreaSize = CHIP_PAGE_SIZE * flash->interleaving;
  3415. flash->pageSize = NFDC21thisVars->pageAreaSize << 1;
  3416. flash->erasableBlockSize = NFDC21thisVars->pagesPerBlock * flash->pageSize;
  3417. NFDC21thisVars->tailSize = EXTRA_LEN * flash->interleaving;/* 8 in interleave-1, 16 in interleave-2 */
  3418. NFDC21thisVars->pageMask = (word)(flash->pageSize - 1);
  3419. NFDC21thisVars->noOfBlocks = (word)(flash->chipSize / flash->erasableBlockSize);
  3420. /* Try changing to interleave 2 */
  3421. changeInterleave(flash, 2);
  3422. /* identify and count flash chips, figure out flash parameters */
  3423. flash->noOfChips = 0; /* One floor already found */
  3424. for( floor = 0; floor < MAX_FLOORS; floor++ )
  3425. {
  3426. setFloor(flash,floor);
  3427. /* check floor for MDOCP ID + check the toggle bit */
  3428. dev = getControllerID(flash); /* Read chip ID */
  3429. if(((dev != CHIP_ID_MDOCP ) &&
  3430. (dev != CHIP_ID_MDOCP16) ) ||
  3431. (checkToggle(flash) == FALSE) )
  3432. break;
  3433. /* check for DPS and OTP download errors */
  3434. if (chkASICDownload (flash,floor))
  3435. {
  3436. DEBUG_PRINT(("Debug: failed to download OTP/DPS.\r\n"));
  3437. return( flBadDownload );
  3438. }
  3439. selectChip (flash, MPLUS_SEL_WP); /* Map window to selected flash device.*/
  3440. }
  3441. /* update total floors in structure and ASIC configuration register */
  3442. flash->noOfChips = floor;
  3443. flash->noOfFloors = floor;
  3444. /* back to ground floor */
  3445. NFDC21thisVars->currentFloor = (byte)0;
  3446. setFloor(flash,NFDC21thisVars->currentFloor);
  3447. if (flash->noOfChips == 0) {
  3448. DEBUG_PRINT(("Debug: failed to identify NFDC MDOCP.\r\n"));
  3449. return( flUnknownMedia );
  3450. }
  3451. /*
  3452. * Open IPL of high floors
  3453. *
  3454. * dev = setIplSize(flash, flash->noOfFloors);
  3455. */
  3456. /* Get host access type (8 bit or 16 bit data access if_cfg */
  3457. NFDC21thisVars->if_cfg = chkIF_CFG(flash);
  3458. /* Register our flash handlers and flash parameters */
  3459. #ifndef FL_READ_ONLY
  3460. flash->write = doc2Write;
  3461. flash->erase = doc2Erase;
  3462. #else
  3463. flash->erase = NULL;
  3464. flash->write = NULL;
  3465. #endif
  3466. flash->read = doc2Read;
  3467. #ifndef MTD_STANDALONE
  3468. flash->map = doc2Map;
  3469. #endif /* MTD_STANDALONE */
  3470. flash->enterDeepPowerDownMode = powerDown;
  3471. #if (defined(HW_PROTECTION) || !defined(NO_IPL_CODE) || defined (HW_OTP))
  3472. flash->download = forceDownLoad;
  3473. #endif /* HW_PROTECTION or !NO_IPL_CODE */
  3474. #ifdef MTD_READ_BBT
  3475. flash->readBBT = readBBT;
  3476. #endif /* MTD_READ_BBT */
  3477. #if (!defined(NO_IPL_CODE) && defined (HW_PROTECTION))
  3478. #ifndef FL_READ_ONLY
  3479. flash->writeIPL = writeIPL;
  3480. #endif /* FL_READ_ONLY */
  3481. flash->readIPL = readIPL;
  3482. #endif /* not NO_IPL_CODE & HW_PROTECTION */
  3483. #ifdef HW_OTP
  3484. flash->otpSize = otpSize;
  3485. flash->readOTP = readOTP;
  3486. #ifndef FL_READ_ONLY
  3487. flash->writeOTP = writeOTP;
  3488. #endif /* FL_READ_ONLY */
  3489. flash->getUniqueId = getUniqueId;
  3490. #endif /* HW_OTP */
  3491. #ifdef HW_PROTECTION
  3492. flash->protectionBoundries = protectionBoundries;
  3493. flash->protectionKeyInsert = protectionKeyInsert;
  3494. flash->protectionKeyRemove = protectionKeyRemove;
  3495. flash->protectionType = protectionType;
  3496. #ifndef FL_READ_ONLY
  3497. flash->protectionSet = protectionSet;
  3498. #endif /* FL_READ_ONLY */
  3499. #endif /* HW_PROTECTION */
  3500. flash->totalProtectedAreas = 2;
  3501. flash->ppp = 5;
  3502. flash->flags = INFTL_ENABLED;
  3503. flash->maxEraseCycles = 1000000L;
  3504. NFDC21thisVars->floorSizeMask = NFDC21thisVars->floorSize-1;
  3505. /* checkStatus(forceDownLoad(flash)); *//* For testing purposes only @@*/
  3506. DEBUG_PRINT(("Debug: identified NFDC MDOCP.\r\n"));
  3507. return( flOK );
  3508. }
  3509. #ifndef MTD_STANDALONE
  3510. /*----------------------------------------------------------------------*/
  3511. /* f l R e g i s t e r D O C P L U S S O C */
  3512. /* */
  3513. /* Installs routines for DiskOnChip Plus family. */
  3514. /* */
  3515. /* Parameters: */
  3516. /* lowAddress, */
  3517. /* highAddress : host memory range to search for DiskOnChip */
  3518. /* PLUS memory window */
  3519. /* */
  3520. /* Returns: */
  3521. /* FLStatus : 0 on success, otherwise failure */
  3522. /*----------------------------------------------------------------------*/
  3523. #ifndef NT5PORT
  3524. FLStatus flRegisterDOCPLUSSOC(dword lowAddress, dword highAddress)
  3525. {
  3526. int serialNo;
  3527. if( noOfSockets >= SOCKETS )
  3528. return flTooManyComponents;
  3529. /* Try to register DiskOnChip using */
  3530. for(serialNo=0;( noOfSockets < SOCKETS );serialNo++,noOfSockets++)
  3531. {
  3532. FLSocket * socket = flSocketOf(noOfSockets);
  3533. socket->volNo = noOfSockets;
  3534. docSocketInit(socket);
  3535. /* call DiskOnChip MTD's routine to search for memory window */
  3536. flSetWindowSize(socket, 2); /* 4 KBytes */
  3537. socket->window.baseAddress = flDocWindowBaseAddress
  3538. ((byte)(socket->volNo), lowAddress, highAddress, &lowAddress);
  3539. if (socket->window.baseAddress == 0) /* DiskOnChip not detected */
  3540. break;
  3541. }
  3542. if( serialNo == 0 )
  3543. return flAdapterNotFound;
  3544. return flOK;
  3545. }
  3546. #endif /* NT5PORT*/
  3547. #else /* MTD_STANDALONE */
  3548. /*----------------------------------------------------------------------*/
  3549. /* d o c P l u s S e a r c h F o r W i n d o w */
  3550. /* */
  3551. /* Search for the DiskOnChip ASIC in a given memory range and */
  3552. /* initialize the given socket record. */
  3553. /* */
  3554. /* Parameters: */
  3555. /* socket : Record used to store the sockets parameters */
  3556. /* lowAddress : host memory range to search for DiskOnChip Plus */
  3557. /* highAddress : memory window */
  3558. /* */
  3559. /* Output: initialize the following fields in the FLFlash record: */
  3560. /* */
  3561. /* base - Pointer to DiskOnChip window */
  3562. /* size - DiskOnChip window size usualy 8K */
  3563. /* */
  3564. /* Returns: */
  3565. /* FLStatus : 0 on success, flDriveNotAvailable on failure. */
  3566. /* */
  3567. /* NOTE: This routine is not used by OSAK. It is used by standalone */
  3568. /* applications using the MTD (BDK for example) as a replacement */
  3569. /* for the OSAK DOCSOC.C file. */
  3570. /* The FLSocket record used by this function is not the one used */
  3571. /* by OSAK defined in flsocket.h but a replacement record defined */
  3572. /* in flflash.h. */
  3573. /* */
  3574. /*----------------------------------------------------------------------*/
  3575. FLStatus docPlusSearchForWindow(FLSocket * socket,
  3576. dword lowAddress,
  3577. dword highAddress)
  3578. {
  3579. dword baseAddress; /* Physical base as a 4K page */
  3580. socket->size = 2 * 0x1000L; /* 4 KBytes */
  3581. baseAddress = (dword) flDocWindowBaseAddress(0, lowAddress, highAddress,&lowAddress);
  3582. socket->base = physicalToPointer(baseAddress << 12, socket->size,0);
  3583. if (baseAddress) /* DiskOnChip detected */
  3584. return flOK;
  3585. else /* DiskOnChip not detected */
  3586. return flDriveNotAvailable;
  3587. }
  3588. #ifndef MTD_FOR_EXB
  3589. /*----------------------------------------------------------------------*/
  3590. /* d o c P l u s F r e e W i n d o w */
  3591. /* */
  3592. /* Free any resources used for the DiskOnChip window */
  3593. /* */
  3594. /* Parameters: */
  3595. /* socket : Record used to store the sockets parameters */
  3596. /* */
  3597. /* Returns: None */
  3598. /* */
  3599. /* NOTE: This routine is used only by virtual memory systems in order */
  3600. /* to unmap the DiskOnChip window. */
  3601. /* */
  3602. /*----------------------------------------------------------------------*/
  3603. void docPlusFreeWindow(FLSocket * socket)
  3604. {
  3605. freePointer(socket->base,DOC_WIN);
  3606. }
  3607. #endif /* MTD_FOR_EXB */
  3608. #endif /* MTD_STANDALONE */
  3609. #ifndef MTD_FOR_EXB
  3610. /*----------------------------------------------------------------------*/
  3611. /* f l R e g i s t e r D O C P L U S */
  3612. /* */
  3613. /* Registers this MTD for use */
  3614. /* */
  3615. /* Parameters: */
  3616. /* None */
  3617. /* */
  3618. /* Returns: */
  3619. /* FLStatus : 0 on success, otherwise failure */
  3620. /*----------------------------------------------------------------------*/
  3621. FLStatus flRegisterDOCPLUS(void)
  3622. {
  3623. if (noOfMTDs >= MTDS)
  3624. return( flTooManyComponents );
  3625. #ifdef MTD_STANDALONE
  3626. socketTable[noOfMTDs] = docPlusSearchForWindow;
  3627. freeTable[noOfMTDs] = docPlusFreeWindow;
  3628. #endif /* MTD_STANDALONE */
  3629. mtdTable[noOfMTDs++] = docPlusIdentify;
  3630. return( flOK );
  3631. }
  3632. #endif /* MTD_FOR_EXB */