00001
00007 #include "uffs/uffs_types.h"
00008 #include "uffs/uffs_config.h"
00009 #include "uffs/uffs_core.h"
00010 #include "uffs/uffs_device.h"
00011 #include "uffs/uffs_os.h"
00012
00013 #include <string.h>
00014
00015 #define PFX "public:"
00016
00017
00018 int uffs_GetFirstBlockTimeStamp(void)
00019 {
00020 return 0;
00021 }
00022
00023 int uffs_GetNextBlockTimeStamp(int prev)
00024 {
00025 return (prev + 1) % 3;
00026 }
00027
00028 UBOOL uffs_IsSrcNewerThanObj(int src, int obj)
00029 {
00030 switch(src - obj) {
00031 case 0:
00032 uffs_Perror(UFFS_ERR_SERIOUS, PFX "the two block have the same time stamp ?\n");
00033 break;
00034 case 1:
00035 case -2:
00036 return U_TRUE;
00037 case -1:
00038 case 2:
00039 return U_FALSE;
00040 default:
00041 uffs_Perror(UFFS_ERR_SERIOUS, PFX "time stamp out of range !\n");
00042 break;
00043 }
00044 return U_FALSE;
00045 }
00046
00047
00048 URET uffs_ECCCheck(uffs_Device *dev, uffs_Buf *buf)
00049 {
00050 return U_SUCC;
00051 }
00052
00058 u8 uffs_CalTagCheckSum(uffs_Tags *tag)
00059 {
00060 u8 checkSum = 0;
00061 int i;
00062 int ofs;
00063
00064 ofs = (int)(&(((uffs_Tags *)NULL)->checkSum));
00065
00066 for(i = 0; i < ofs; i++) {
00067 checkSum += *((u8 *)(tag) + i);
00068 }
00069 return checkSum;
00070 }
00071
00072
00080 u16 uffs_FindBestPageInBlock(uffs_Device *dev, uffs_blockInfo *bc, u16 page)
00081 {
00082 uffs_pageSpare *spare_old, *spare;
00083 int i;
00084 int best;
00085
00086 if(page == dev->attr.pages_per_block - 1) return page;
00087
00088 uffs_LoadBlockInfo(dev, bc, page);
00089 spare_old = &(bc->spares[page]);
00090
00091 if(spare_old->tag.pageID == page) {
00092
00093 uffs_LoadBlockInfo(dev, bc, dev->attr.pages_per_block - 1);
00094 spare = &(bc->spares[dev->attr.pages_per_block - 1]);
00095 if(spare->tag.pageID == dev->attr.pages_per_block - 1) {
00096 return page;
00097 }
00098 }
00099
00100 uffs_LoadBlockInfo(dev, bc, UFFS_ALL_PAGES);
00101 best = page;
00102
00103 for(i = page + 1; i < dev->attr.pages_per_block; i++) {
00104 spare = &(bc->spares[i]);
00105 if(spare->tag.pageID == spare_old->tag.pageID) {
00106 if( spare->tag.father == spare_old->tag.father &&
00107 spare->tag.serial == spare_old->tag.serial &&
00108 spare->tag.dirty == TAG_DIRTY &&
00109 spare->tag.valid == TAG_VALID) {
00110 if(i > best) best = i;
00111 }
00112 }
00113 }
00114 return best;
00115 }
00116
00126 u16 uffs_FindPageInBlockWithPageId(uffs_Device *dev, uffs_blockInfo *bc, u16 pageID)
00127 {
00128 u16 page;
00129 uffs_Tags *tag;
00130
00131
00132 for(page = pageID; page < dev->attr.pages_per_block; page++) {
00133 uffs_LoadBlockInfo(dev, bc, page);
00134 tag = &(bc->spares[page].tag);
00135 if(tag->pageID == pageID) return page;
00136 }
00137 return UFFS_INVALID_PAGE;
00138 }
00139
00143 UBOOL uffs_IsBlockPagesFullUsed(uffs_Device *dev, uffs_blockInfo *bc)
00144 {
00145 uffs_LoadBlockInfo(dev, bc, dev->attr.pages_per_block - 1);
00146 if(bc->spares[dev->attr.pages_per_block - 1].tag.dirty == TAG_DIRTY) return U_TRUE;
00147
00148 return U_FALSE;
00149 }
00150
00158 UBOOL uffs_IsThisBlockUsed(uffs_Device *dev, uffs_blockInfo *bc)
00159 {
00160 uffs_LoadBlockInfo(dev, bc, 0);
00161 if(bc->spares[0].tag.dirty == TAG_DIRTY) return U_TRUE;
00162
00163 return U_FALSE;
00164 }
00165
00171 int uffs_GetBlockTimeStamp(uffs_Device *dev, uffs_blockInfo *bc)
00172 {
00173 if(uffs_IsThisBlockUsed(dev, bc) == U_FALSE)
00174 return uffs_GetFirstBlockTimeStamp();
00175 else{
00176 uffs_LoadBlockInfo(dev, bc, 0);
00177 return bc->spares[0].tag.blockTimeStamp;
00178 }
00179
00180 }
00181
00191 u16 uffs_FindFirstFreePage(uffs_Device *dev, uffs_blockInfo *bc, u16 pageFrom)
00192 {
00193 u16 i;
00194
00195 for(i = pageFrom; i < dev->attr.pages_per_block; i++) {
00196 uffs_LoadBlockInfo(dev, bc, i);
00197 if(uffs_IsPageErased(dev, bc, i) == U_TRUE)
00198 return i;
00199 }
00200 return UFFS_INVALID_PAGE;
00201 }
00202
00203
00207 u16 uffs_FindFirstValidPage(uffs_Device *dev, uffs_blockInfo *bc)
00208 {
00209 u16 i;
00210 for(i = 0; i < dev->attr.pages_per_block; i++) {
00211 uffs_LoadBlockInfo(dev, bc, i);
00212 if(bc->spares[i].checkOk) return i;
00213 }
00214 return UFFS_INVALID_PAGE;
00215 }
00216
00225 URET uffs_WriteDataToNewPage(uffs_Device *dev,
00226 u16 block,
00227 u16 page,
00228 uffs_Tags *tag,
00229 uffs_Buf *buf)
00230 {
00231 URET ret = U_SUCC;
00232
00233 tag->dirty = 0;
00234 tag->valid = 1;
00235 tag->checkSum = 0xff;
00236
00237
00238
00239
00240
00241 ret = dev->flash->WritePageSpare(dev, block, page, tag);
00242 if(ret != U_SUCC)
00243 return ret;
00244
00245
00246 dev->flash->MakeEcc(dev, buf->data, buf->ecc);
00247 ret = dev->ops->WritePageData(dev, block, page, buf->data, 0, dev->com.pgSize);
00248 if(ret != U_SUCC)
00249 return ret;
00250
00251
00252 tag->valid = 0;
00253 tag->checkSum = uffs_CalTagCheckSum(tag);
00254 ret = dev->flash->MakePageValid(dev, block, page, tag);
00255 if(ret != U_SUCC)
00256 return ret;
00257
00258 return U_SUCC;
00259 }
00260
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00314 u8 uffs_MakeSum8(void *p, int len)
00315 {
00316 u8 ret = 0;
00317 u8 *data = (u8 *)p;
00318 while(len > 0) {
00319 ret += *data++;
00320 len--;
00321 }
00322 return ret;
00323 }
00324
00331 u16 uffs_MakeSum16(void *p, int len)
00332 {
00333 u8 ret_lo = 0;
00334 u8 ret_hi = 0;
00335 u8 *data = (u8 *)p;
00336 while(len > 0) {
00337 ret_lo += *data;
00338 ret_hi ^= *data;
00339 data++;
00340 len--;
00341 }
00342 return (ret_hi << 8) | ret_lo;
00343 }
00344
00354 URET uffs_CreateNewFile(uffs_Device *dev, u16 father, u16 serial, uffs_blockInfo *bc, uffs_fileInfo *fi)
00355 {
00356 uffs_Tags *tag;
00357 uffs_Buf *buf;
00358
00359 fi->createTime = fi->lastModify = uffs_GetCurDateTime();
00360
00361 uffs_LoadBlockInfo(dev, bc, 0);
00362
00363 tag = &(bc->spares[0].tag);
00364 tag->father = father;
00365 tag->serial = serial;
00366 tag->dataLength = sizeof(uffs_fileInfo);
00367 tag->dataSum = uffs_MakeSum16(fi->name, fi->name_len);
00368
00369 buf = uffs_BufGet(dev, father, serial, 0);
00370 if(buf == NULL) {
00371 uffs_Perror(UFFS_ERR_SERIOUS, PFX"get buf fail.\n");
00372 return U_FAIL;
00373 }
00374
00375 memcpy(buf->data, fi, tag->dataLength);
00376 buf->dataLen = tag->dataLength;
00377
00378 return uffs_BufPut(dev, buf);
00379 }
00380
00381
00387 int uffs_GetBlockFileDataLength(uffs_Device *dev, uffs_blockInfo *bc, u8 type)
00388 {
00389 u16 pageID;
00390 u16 i;
00391 uffs_Tags *tag;
00392 int size = 0;
00393 u16 page;
00394 u16 lastPage = dev->attr.pages_per_block - 1;
00395
00396
00397 uffs_LoadBlockInfo(dev, bc, lastPage);
00398 tag = &(bc->spares[lastPage].tag);
00399
00400 if(type == UFFS_TYPE_FILE) {
00401 if(tag->pageID == (lastPage - 1) &&
00402 tag->dataLength == dev->com.pgDataSize) {
00403 size = dev->com.pgDataSize * (dev->attr.pages_per_block - 1);
00404 return size;
00405 }
00406 }
00407 if(type == UFFS_TYPE_DATA) {
00408 if(tag->pageID == lastPage &&
00409 tag->dataLength == dev->com.pgDataSize) {
00410 size = dev->com.pgDataSize * dev->attr.pages_per_block;
00411 return size;
00412 }
00413 }
00414
00415
00416 uffs_LoadBlockInfo(dev, bc, UFFS_ALL_PAGES);
00417 tag = &(bc->spares[0].tag);
00418 if(tag->type == UFFS_TYPE_FILE) {
00419 pageID = 1;
00420 i = 1;
00421 }
00422 else {
00423 pageID = 0;
00424 i = 0;
00425 }
00426 for(; i < dev->attr.pages_per_block; i++) {
00427 tag = &(bc->spares[i].tag);
00428 if(pageID == tag->pageID) {
00429 page = uffs_FindBestPageInBlock(dev, bc, i);
00430 size += bc->spares[page].tag.dataLength;
00431 pageID++;
00432 }
00433 }
00434 return size;
00435 }
00436
00442 int uffs_GetFreePagesCount(uffs_Device *dev, uffs_blockInfo *bc)
00443 {
00444 int count = 0;
00445 int i;
00446
00447 for(i = dev->attr.pages_per_block - 1; i >= 0; i--) {
00448 uffs_LoadBlockInfo(dev, bc, i);
00449 if(uffs_IsPageErased(dev, bc, (u16)i) == U_TRUE) {
00450 count++;
00451 }
00452 else break;
00453 }
00454 return count;
00455 }
00464 UBOOL uffs_IsPageErased(uffs_Device *dev, uffs_blockInfo *bc, u16 page)
00465 {
00466 uffs_Tags *tag;
00467
00468 uffs_LoadBlockInfo(dev, bc, page);
00469 tag = &(bc->spares[page].tag);
00470
00471 if(tag->dirty == TAG_CLEAR &&
00472 tag->valid == TAG_INVALID &&
00473 tag->checkSum == 0xff) {
00474 return U_TRUE;
00475 }
00476
00477 return U_FALSE;
00478 }
00479
00483 UBOOL uffs_IsDataBlockReguFull(uffs_Device *dev, uffs_blockInfo *bc)
00484 {
00485 uffs_LoadBlockInfo(dev, bc, dev->attr.pages_per_block - 1);
00486 if(bc->spares[dev->attr.pages_per_block - 1].tag.pageID == (dev->attr.pages_per_block - 1) &&
00487 bc->spares[dev->attr.pages_per_block - 1].tag.dataLength == dev->com.pgDataSize) {
00488 return U_TRUE;
00489 }
00490 return U_FALSE;
00491 }
00492
00496 int uffs_GetDeviceUsed(uffs_Device *dev)
00497 {
00498 return (dev->par.end - dev->par.start + 1 - dev->tree.badCount
00499 - dev->tree.erasedCount) * dev->attr.block_data_size;
00500 }
00501
00505 int uffs_GetDeviceFree(uffs_Device *dev)
00506 {
00507 return dev->tree.erasedCount * dev->attr.block_data_size;
00508 }
00509
00513 int uffs_GetDeviceTotal(uffs_Device *dev)
00514 {
00515 return (dev->par.end - dev->par.start + 1) * dev->attr.block_data_size;
00516 }
00517