uffs_public.c

Go to the documentation of this file.
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); //load old page
00089     spare_old = &(bc->spares[page]);
00090 
00091     if(spare_old->tag.pageID == page) {
00092         //well, try to speed up ....
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     //the better page must be ahead of page, so ...i = page + 1; i < ...
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 && //0: dirty, 1:clear
00109                 spare->tag.valid == TAG_VALID) { //0: valid, 1:invalid
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     //Indeed, the page which has pageID, should ahead of pageID ...
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; //free page not found
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 //  uffs_Perror(UFFS_ERR_NOISY, PFX"write b:%d p:%d t:%d f:%d s:%d id:%d L:%d\n",
00238 //              block, page, buf->type, buf->father, buf->serial, buf->pageID, buf->dataLen);
00239 
00240     //step 1: write spare
00241     ret = dev->flash->WritePageSpare(dev, block, page, tag);
00242     if(ret != U_SUCC)
00243         return ret;
00244     
00245     //step 2: write page data
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     //step 3: write spare again, make page valid
00252     tag->valid = 0;
00253     tag->checkSum = uffs_CalTagCheckSum(tag); //calculate right check sum
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 // * \brief recover a page in block
00263 // * \param[in] dev uffs device
00264 // * \parma[in] bc block information buffer
00265 // * \param[in] oldPage old page number
00266 // * \param[in] newPage new page number
00267 // * \param[in] buf new page data buffer
00268 // * \note the new data and length should be set to buf before this function invoked
00269 // */
00270 //URET uffs_PageRecover(uffs_Device *dev, 
00271 //                    uffs_blockInfo *bc, 
00272 //                    int oldPage, 
00273 //                    int newPage, 
00274 //                    uffs_Buf *buf)
00275 //{
00276 //  uffs_Tags *oldTag, *newTag;
00277 //  uffs_pageSpare *newSpare;
00278 //
00279 //  if(newPage < 0 || newPage >= dev->attr.pages_per_block) {
00280 //      uffs_Perror(UFFS_ERR_SERIOUS, PFX "new page number outof range!\n");
00281 //      return U_FAIL;
00282 //  }
00283 //
00284 //  uffs_LoadBlockInfo(dev, bc, oldPage);
00285 //  uffs_LoadBlockInfo(dev, bc, newPage);
00286 //
00287 //  oldTag = &(bc->spares[oldPage].tag);    
00288 //  newTag = &(bc->spares[newPage].tag);    
00289 //
00290 //  newSpare = &(bc->spares[newPage]);
00291 //
00292 //  newSpare->expired = 1; // make it expired firstly
00293 //
00294 //  newTag->fdn = oldTag->fdn;
00295 //  newTag->blockTimeStamp = oldTag->blockTimeStamp;
00296 //  newTag->fsn = oldTag->fsn;
00297 //  newTag->pageID = oldTag->pageID;
00298 //  newTag->dirty = 0;
00299 //  newTag->dataLength = buf->dataLen;
00300 //  newTag->checkSum = 0xff; //set check sum with 0xff first.
00301 //  newTag->valid = 1;
00302 //
00303 //  uffs_WriteDataToNewPage(dev, bc->blockNum, newPage, newTag, buf);
00304 //
00305 //  return U_SUCC;
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     //@ Need to speed up this procedure!
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     //normal procedure....
00416     uffs_LoadBlockInfo(dev, bc, UFFS_ALL_PAGES);
00417     tag = &(bc->spares[0].tag);
00418     if(tag->type == UFFS_TYPE_FILE) {
00419         pageID = 1; //In file header block, file data pageID from 1
00420         i = 1;      //search from page 1
00421     }
00422     else {
00423         pageID = 0; //in normal file data block, pageID from 0
00424         i = 0;      //in normal file data block, search from page 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 

Generated on Sat Mar 17 15:45:45 2007 for uffs-doc by  doxygen 1.5.0