00001
00007 #include "uffs/uffs_public.h"
00008 #include "uffs/uffs_ecc.h"
00009 #include <string.h>
00010
00011 #define PFX "samsung NAND:"
00012
00013 #define SAMSUNG_ECC_LEN 6
00014 #define SAMSUNG_SPARE_LENGTH 16
00015 #define SAMSUNG_BLOCK_STATUS_OFS 5
00016
00021 struct uffs_SamsungSpareSt {
00022 u8 x[SAMSUNG_SPARE_LENGTH];
00023 };
00024
00025 typedef struct uffs_SamsungSpareSt uffs_SamsungSpare;
00026
00027
00028
00036 URET Samsung_LoadPageSpare(uffs_Device *dev, int block, int page, uffs_Tags *tag)
00037 {
00038 uffs_SamsungSpare phi_spare;
00039 u8 * p = (u8 *)(tag);
00040 u8 * p_spare = (u8 *) &phi_spare;
00041 u32 ofs_end;
00042
00043 dev->ops->ReadPage(dev, block, page, NULL, p_spare);
00044
00046 memcpy(p, p_spare, SAMSUNG_BLOCK_STATUS_OFS);
00047 p += (SAMSUNG_BLOCK_STATUS_OFS);
00048 p_spare += SAMSUNG_BLOCK_STATUS_OFS;
00049 p_spare++;
00050
00051 ofs_end = (u32)(&(((uffs_Tags *)NULL)->blockStatus));
00052 memcpy(p, p_spare, ofs_end - (SAMSUNG_BLOCK_STATUS_OFS));
00053 tag->blockStatus = phi_spare.x[SAMSUNG_BLOCK_STATUS_OFS];
00054
00055 return U_SUCC;
00056 }
00057
00068 URET Samsung_WritePageSpare(uffs_Device *dev, int block, int page, uffs_Tags *tag)
00069 {
00070 uffs_SamsungSpare phi_spare;
00071 u8 * p = (u8 *)tag;
00072 u8 * p_spare = (u8 *) &phi_spare;
00073 u32 ofs_end;
00074
00075 dev->ops->ReadPage(dev, block, page, NULL, (u8 *)(&phi_spare));
00076
00077 if(page == 0 || page == 1) {
00078 if(phi_spare.x[SAMSUNG_BLOCK_STATUS_OFS] != 0xff) {
00079 uffs_Perror(UFFS_ERR_SERIOUS, PFX"try to write to a bad block(%d) ? \n", block);
00080 return U_FAIL;
00081 }
00082 }
00083
00084 memcpy(p_spare, p, SAMSUNG_BLOCK_STATUS_OFS);
00085 p += (SAMSUNG_BLOCK_STATUS_OFS);
00086 p_spare += SAMSUNG_BLOCK_STATUS_OFS;
00087 p_spare++;
00088 ofs_end = (u32)(&(((uffs_Tags *)NULL)->blockStatus));
00089 memcpy(p_spare, p, ofs_end - (SAMSUNG_BLOCK_STATUS_OFS));
00090
00091 return dev->ops->WritePage(dev, block, page, NULL, (u8 *)(&phi_spare));
00092 }
00093
00101 URET Samsung_MakePageValid(uffs_Device *dev, int block, int page, uffs_Tags *tag)
00102 {
00103
00104 return Samsung_WritePageSpare(dev, block, page, tag);
00105 }
00106
00112 int Samsung_GetEccSize(uffs_Device *dev)
00113 {
00114 return SAMSUNG_ECC_LEN;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123 UBOOL Samsung_IsBlockBad(uffs_Device *dev, uffs_blockInfo *bc)
00124 {
00125 uffs_LoadBlockInfo(dev, bc, 0);
00126 #ifdef SAFE_CHECK_BAD_BLOCK_DOUBLE
00127 uffs_LoadBlockInfo(dev, bc, 1);
00128 #endif
00129 if(bc->spares[0].tag.blockStatus != 0xff
00130 #ifdef SAFE_CHECK_BAD_BLOCK_DOUBLE
00131 || bc->spares[1].tag.blockStatus != 0xff
00132 #endif
00133 ) {
00134 return U_TRUE;
00135 }
00136
00137 return U_FALSE;
00138 }
00139
00140 URET Samsung_MakeBadBlockMark(uffs_Device *dev, int block)
00141 {
00142 u8 mark = 0;
00143
00144 dev->ops->ReadPageSpare(dev, block, 0, &mark, SAMSUNG_BLOCK_STATUS_OFS, 1);
00145 if(mark == 0xff){
00146 uffs_Perror(UFFS_ERR_NOISY, PFX"New bad block generated! %d\n", block);
00147 dev->ops->WritePageSpare(dev, block, 0, (u8 *)"1", SAMSUNG_BLOCK_STATUS_OFS, 1);
00148 }
00149
00150 return U_SUCC;
00151 }
00152
00153
00154 static struct uffs_FlashOpsSt Samsung_Flash = {
00155 Samsung_LoadPageSpare,
00156 Samsung_WritePageSpare,
00157 Samsung_MakePageValid,
00158 uffs_GetEccSize512,
00159 uffs_MakeEcc512,
00160 uffs_EccCorrect512,
00161 Samsung_IsBlockBad,
00162 Samsung_MakeBadBlockMark
00163 };
00164
00166 static int valid_id_list[] = {0xe3, 0xe5, 0xe6, 0x73, 0x75, 0x76, 0x79, 0x35, 0x36, -1};
00167
00168
00169 struct uffs_FlashClassSt Samsung_FlashClass = {
00170 "Samsung NAND",
00171 0xec,
00172 valid_id_list,
00173 &Samsung_Flash,
00174 };
00175
00176