00001
00008 #include "uffs/uffs_types.h"
00009 #include "uffs/uffs_buf.h"
00010 #include "uffs/uffs_device.h"
00011 #include "uffs/uffs_os.h"
00012 #include "uffs/uffs_public.h"
00013 #include "uffs/ubuffer.h"
00014 #include "uffs/uffs_ecc.h"
00015 #include "uffs/uffs_badblock.h"
00016 #include <string.h>
00017
00018 #define PFX "pg buf:"
00019
00020
00029 URET uffs_BufInit(uffs_Device *dev, int maxBuf, int maxDirtyBuf)
00030 {
00031 void *pool;
00032 u8 *data;
00033 uffs_Buf *buf;
00034 int size;
00035 int i;
00036
00037 if(!dev) return U_FAIL;
00038
00039
00040 dev->com.pgSize = dev->attr.page_data_size;
00041 dev->com.eccSize = dev->flash->GetEccSize(dev);
00042 dev->com.pgDataSize = dev->com.pgSize - dev->com.eccSize;
00043
00044 if(dev->buf.pool != NULL) {
00045 uffs_Perror(UFFS_ERR_NORMAL, PFX"buf.pool is not NULL, buf already inited ?\n");
00046 return U_FAIL;
00047 }
00048
00049 size = (sizeof(uffs_Buf) + dev->com.pgSize) * maxBuf;
00050 pool = uffs_MemAlloc(dev, size);
00051 if(pool == NULL) {
00052 uffs_Perror(UFFS_ERR_NORMAL, PFX"allocate mem fail!\n");
00053 return U_FAIL;
00054 }
00055
00056 uffs_Perror(UFFS_ERR_NOISY, PFX"allcate %d bytes.\n", size);
00057 dev->buf.pool = pool;
00058
00059 data = (u8 *)pool + (sizeof(uffs_Buf) * maxBuf);
00060
00061 for(i = 0; i < maxBuf; i++) {
00062 buf = (uffs_Buf *)((u8 *)pool + (sizeof(uffs_Buf) * i));
00063 memset(buf, 0, sizeof(uffs_Buf));
00064 data = (u8 *)pool + (sizeof(uffs_Buf) * maxBuf) + (dev->com.pgSize * i);
00065
00066 buf->data = data;
00067 buf->ecc = data + dev->com.pgDataSize;
00068 buf->mark = UFFS_BUF_EMPTY;
00069 if(i == 0) {
00070 buf->prev = NULL;
00071 dev->buf.bufHead = buf;
00072 }
00073 else {
00074 buf->prev = (uffs_Buf *)((u8 *)buf - sizeof(uffs_Buf));
00075 }
00076
00077 if(i == maxBuf - 1) {
00078 buf->next = NULL;
00079 dev->buf.bufTail = buf;
00080 }
00081 else {
00082 buf->next = (uffs_Buf *)((u8 *)buf + sizeof(uffs_Buf));
00083 }
00084 }
00085
00086 dev->buf.maxBuf = maxBuf;
00087 dev->buf.maxDirtyBuf = (maxDirtyBuf > dev->attr.pages_per_block ? dev->attr.pages_per_block : maxDirtyBuf);
00088 dev->buf.dirty = NULL;
00089 dev->buf.dirtyCount = 0;
00090
00091 return U_SUCC;
00092 }
00093
00100 URET uffs_BufReleaseAll(uffs_Device *dev)
00101 {
00102 uffs_Buf *p;
00103
00104 if(!dev) return U_FAIL;
00105
00106 uffs_DeviceLock(dev);
00107
00108
00109 p = dev->buf.bufHead;
00110 while(p) {
00111 if(p->refCount != 0) {
00112 uffs_Perror(UFFS_ERR_NORMAL,
00113 PFX "can't release buffers, \
00114 father:%d, serial:%d, pageID:%d still in used.\n", p->father, p->serial, p->pageID);
00115 uffs_DeviceUnLock(dev);
00116 return U_FAIL;
00117 }
00118 p = p->next;
00119 }
00120
00121 if(uffs_BufFlush(dev) != U_SUCC) {
00122 uffs_Perror(UFFS_ERR_NORMAL, PFX"can't release buf, fail to flush buffer\n");
00123 uffs_DeviceUnLock(dev);
00124 return U_FAIL;
00125 }
00126
00127 uffs_MemFree(dev, dev->buf.pool);
00128 dev->buf.pool = NULL;
00129 dev->buf.bufHead = dev->buf.bufTail = NULL;
00130
00131 uffs_DeviceUnLock(dev);
00132 return U_SUCC;
00133 }
00134
00135
00136 static void _BreakFromBufList(uffs_Device *dev, uffs_Buf *buf)
00137 {
00138 if(buf->next) {
00139 buf->next->prev = buf->prev;
00140 }
00141 if(buf->prev) {
00142 buf->prev->next = buf->next;
00143 }
00144 if(dev->buf.bufHead == buf) {
00145 dev->buf.bufHead = buf->next;
00146 }
00147 if(dev->buf.bufTail == buf) {
00148 dev->buf.bufTail = buf->prev;
00149 }
00150 }
00151
00152 static void _LinkToBufListHead(uffs_Device *dev, uffs_Buf *buf)
00153 {
00154 if(buf == dev->buf.bufHead) return;
00155 buf->prev = NULL;
00156 buf->next = dev->buf.bufHead;
00157 if(dev->buf.bufHead) dev->buf.bufHead->prev = buf;
00158 if(dev->buf.bufTail == NULL) dev->buf.bufTail = buf;
00159 dev->buf.bufHead = buf;
00160 }
00161
00162 static void _LinkToBufListTail(uffs_Device *dev, uffs_Buf *buf)
00163 {
00164 if(dev->buf.bufTail == buf) return;
00165 buf->prev = dev->buf.bufTail;
00166 buf->next = NULL;
00167 if(dev->buf.bufTail) dev->buf.bufTail->next = buf;
00168 if(dev->buf.bufHead == NULL) dev->buf.bufHead = buf;
00169 dev->buf.bufTail = buf;
00170 }
00171
00172
00173 static void _MoveNodeToHead(uffs_Device *dev, uffs_Buf *p)
00174 {
00175 if(p == dev->buf.bufHead) return;
00176
00177
00178 _BreakFromBufList(dev, p);
00179
00180
00181 _LinkToBufListHead(dev, p);
00182 }
00183
00184 static void _LinkToDirtyList(uffs_Device *dev, uffs_Buf *buf)
00185 {
00186 if (buf == NULL) {
00187 uffs_Perror(UFFS_ERR_SERIOUS, PFX"Try to insert a NULL node into dirty list ?\n");
00188 return;
00189 }
00190 buf->mark = UFFS_BUF_DIRTY;
00191 buf->prevDirty = NULL;
00192 buf->nextDirty = dev->buf.dirty;
00193 if(dev->buf.dirty) dev->buf.dirty->prevDirty = buf;
00194 dev->buf.dirty = buf;
00195 dev->buf.dirtyCount++;
00196 }
00197
00198 static uffs_Buf * _FindFreeBuf(uffs_Device *dev)
00199 {
00200 uffs_Buf *buf;
00201 #if 1
00202 buf = dev->buf.bufHead;
00203 while(buf) {
00204 if(buf->refCount == 0 &&
00205 buf->mark != UFFS_BUF_DIRTY) return buf;
00206 buf = buf->next;
00207 }
00208 #else
00209 buf = dev->buf.bufTail;
00210 while(buf) {
00211 if(buf->refCount == 0 &&
00212 buf->mark != UFFS_BUF_DIRTY) return buf;
00213 buf = buf->prev;
00214 }
00215 #endif
00216
00217 return buf;
00218 }
00219
00228 URET uffs_LoadPhiDataToBuf(uffs_Device *dev, uffs_Buf *buf, u32 block, u32 page)
00229 {
00230 URET ret;
00231
00232 ret = dev->ops->ReadPageData(dev, block, page, buf->data, 0, dev->com.pgSize);
00233 if(ret == U_SUCC) {
00234 if (uffs_CheckBadBlock(dev, buf, block) == U_SUCC) {
00235 buf->mark = UFFS_BUF_VALID;
00236 }
00237 else {
00238 buf->mark = UFFS_BUF_EMPTY;
00239 ret = U_FAIL;
00240 }
00241 }
00242 else {
00243 buf->mark = UFFS_BUF_EMPTY;
00244 }
00245
00246 return ret;
00247 }
00248
00258 URET uffs_LoadPhiDataToBufEccUnCare(uffs_Device *dev, uffs_Buf *buf, u32 block, u32 page)
00259 {
00260 URET ret;
00261
00262 ret = dev->ops->ReadPageData(dev, block, page, buf->data, 0, dev->com.pgSize);
00263 if(ret == U_SUCC) {
00264 if (uffs_CheckBadBlock(dev, buf, block) == U_SUCC) {
00265
00266 buf->mark = UFFS_BUF_VALID;
00267 }
00268 return U_SUCC;
00269 }
00270 else {
00271 buf->mark = UFFS_BUF_EMPTY;
00272 }
00273
00274 return ret;
00275 }
00276
00277
00286 uffs_Buf * uffs_BufFind(uffs_Device *dev, u16 father, u16 serial, u16 pageID)
00287 {
00288 uffs_Buf *p = dev->buf.bufHead;
00289
00290 while(p) {
00291 if( p->father == father &&
00292 p->serial == serial &&
00293 p->pageID == pageID &&
00294 p->mark != UFFS_BUF_EMPTY) {
00295
00296 return p;
00297 }
00298 p = p->next;
00299 }
00300
00301 return NULL;
00302 }
00303
00304 static uffs_Buf * _FindBufInDirtyList(uffs_Buf *dirty, u16 pageID)
00305 {
00306 while(dirty) {
00307 if(dirty->pageID == pageID) return dirty;
00308 dirty = dirty->nextDirty;
00309 }
00310 return NULL;
00311 }
00312
00313 static URET _BreakFromDirty(uffs_Device *dev, uffs_Buf *dirtyBuf)
00314 {
00315 if(dirtyBuf->mark != UFFS_BUF_DIRTY) {
00316 uffs_Perror(UFFS_ERR_NORMAL, PFX"try to break a non-dirty buf from dirty list ?\n");
00317 return U_FAIL;
00318 }
00319
00320 if(dev->buf.dirty == NULL) {
00321 uffs_Perror(UFFS_ERR_NORMAL, PFX"no dirty list exit ?\n");
00322 return U_FAIL;
00323 }
00324
00325 if(dirtyBuf->nextDirty) {
00326 dirtyBuf->nextDirty->prevDirty = dirtyBuf->prevDirty;
00327 }
00328 if(dirtyBuf->prevDirty) {
00329 dirtyBuf->prevDirty->nextDirty = dirtyBuf->nextDirty;
00330 }
00331 if(dev->buf.dirty == dirtyBuf) {
00332
00333 dev->buf.dirty = dirtyBuf->nextDirty;
00334 }
00335
00336 dev->buf.dirtyCount--;
00337
00338 return U_SUCC;
00339 }
00340
00341 static u16 _GetDataSum(uffs_Device *dev, uffs_Buf *buf)
00342 {
00343 u16 dataSum = 0;
00344 uffs_fileInfo *fi;
00345
00346
00347 if(buf->type == UFFS_TYPE_FILE || buf->type == UFFS_TYPE_DIR) {
00348 if(buf->pageID == 0) {
00349 fi = (uffs_fileInfo *)(buf->data);
00350 dataSum = uffs_MakeSum16(fi->name, fi->name_len);
00351 }
00352 }
00353
00354 return dataSum;
00355 }
00356
00357
00358 static URET _CheckDirtyList(uffs_Device *dev)
00359 {
00360 uffs_Buf *dirty = dev->buf.dirty;
00361 u16 father;
00362 u16 serial;
00363
00364 if(dirty == NULL) {
00365 return U_SUCC;
00366 }
00367
00368 father = dirty->father;
00369 serial = dirty->serial;
00370 dirty = dirty->nextDirty;
00371
00372 while(dirty) {
00373 if(father != dirty->father ||
00374 serial != dirty->serial) {
00375 uffs_Perror(UFFS_ERR_SERIOUS, PFX"father or serial in dirty pages buffer are not the same ?\n");
00376 return U_FAIL;
00377 }
00378 if(dirty->mark != UFFS_BUF_DIRTY) {
00379 uffs_Perror(UFFS_ERR_SERIOUS, PFX"non-dirty page buffer in dirty buffer list ?\n");
00380 return U_FAIL;
00381 }
00382 dirty = dirty->nextDirty;
00383 }
00384 return U_SUCC;
00385 }
00386
00388 uffs_Buf * _FindMinimunPageIdFromDirtyList(uffs_Buf *dirtyList)
00389 {
00390 uffs_Buf * work = dirtyList;
00391 uffs_Buf * buf = dirtyList;
00392
00393 work = work->nextDirty;
00394 while(work) {
00395 if(work->pageID < buf->pageID) buf = work;
00396 work = work->nextDirty;
00397 }
00398 return buf;
00399 }
00400
00406 static
00407 URET
00408 _BufFlush_Exist_With_Enough_FreePage(
00409 uffs_Device *dev,
00410 uffs_blockInfo *bc,
00411 u16 freePages
00412 )
00413 {
00414 u16 page;
00415 uffs_Buf *buf;
00416 uffs_Tags *tag;
00417 URET ret;
00418
00419
00420
00421
00422 for(page = dev->attr.pages_per_block - freePages;
00423 dev->buf.dirtyCount > 0;
00424 page++) {
00425
00426 buf = _FindMinimunPageIdFromDirtyList(dev->buf.dirty);
00427 if(buf == NULL) {
00428 uffs_Perror(UFFS_ERR_SERIOUS, PFX"dirtyCount > 0, but no dirty pages in list ?\n");
00429 return U_FAIL;
00430 }
00431
00432
00433
00434 uffs_LoadBlockInfo(dev, bc, page);
00435 tag = &(bc->spares[page].tag);
00436 tag->blockTimeStamp = uffs_GetBlockTimeStamp(dev, bc);
00437 tag->dataLength = buf->dataLen;
00438 tag->type = buf->type;
00439 tag->dataSum = _GetDataSum(dev, buf);
00440 tag->father = buf->father;
00441 tag->serial = buf->serial;
00442 tag->pageID = (u8)(buf->pageID);
00443 ret = uffs_WriteDataToNewPage(dev, bc->blockNum, page, tag, buf);
00444 if(ret == U_SUCC) {
00445 if(_BreakFromDirty(dev, buf) == U_SUCC) {
00446 buf->mark = UFFS_BUF_VALID;
00447 _MoveNodeToHead(dev, buf);
00448 }
00449 }
00450 else{
00451 uffs_Perror(UFFS_ERR_NORMAL, PFX"I/O error <1>?\n");
00452 return U_FAIL;
00453 }
00454 }
00455
00456 if(dev->buf.dirty != NULL || dev->buf.dirtyCount != 0) {
00457 uffs_Perror(UFFS_ERR_NORMAL, PFX"still has dirty buffer ?\n");
00458 }
00459 return U_SUCC;
00460 }
00461
00462
00471 static URET _BufFlush_NewBlock(uffs_Device *dev)
00472 {
00473 u8 type;
00474 u16 father, serial;
00475 uffs_Buf *dirty, *buf;
00476 TreeNode *node;
00477 u16 i;
00478 uffs_blockInfo *bc;
00479 uffs_Tags *tag;
00480 URET ret;
00481
00482 dirty = dev->buf.dirty;
00483 type = dirty->type;
00484 father = dirty->father;
00485 serial = dirty->serial;
00486
00487
00488
00489 node = uffs_GetErased(dev);
00490 if(node == NULL) {
00491 uffs_Perror(UFFS_ERR_NOISY, PFX"no erased block!\n");
00492 return U_FAIL;
00493 }
00494 bc = uffs_GetBlockInfo(dev, node->u.list.block);
00495 if(bc == NULL) {
00496 uffs_Perror(UFFS_ERR_SERIOUS, PFX"get block info fail!\n");
00497 uffs_InsertToErasedListHead(dev, node);
00498 return U_FAIL;
00499 }
00500
00501
00502
00503
00504 for(i = 0; i < dev->attr.pages_per_block; i++) {
00505 buf = _FindBufInDirtyList(dirty, i);
00506 if(buf == NULL) break;
00507 uffs_LoadBlockInfo(dev, bc, i);
00508 tag = &(bc->spares[i].tag);
00509 tag->blockTimeStamp = uffs_GetFirstBlockTimeStamp();
00510 tag->dataLength = buf->dataLen;
00511 tag->dataSum = _GetDataSum(dev, buf);
00512 tag->type = type;
00513 tag->father = buf->father;
00514 tag->serial = buf->serial;
00515 tag->pageID = (u8)(buf->pageID);
00516 ret = uffs_WriteDataToNewPage(dev, node->u.list.block, i, tag, buf);
00517 if(ret == U_SUCC) {
00518 if(_BreakFromDirty(dev, buf) == U_SUCC) {
00519 buf->mark = UFFS_BUF_VALID;
00520 _MoveNodeToHead(dev, buf);
00521 }
00522 }
00523 else{
00524 uffs_Perror(UFFS_ERR_NORMAL, PFX"I/O error <2>?\n");
00525 uffs_PutBlockInfo(dev, bc);
00526 return U_FAIL;
00527 }
00528 }
00529
00530
00531 switch(type) {
00532 case UFFS_TYPE_DIR:
00533 node->u.dir.block = bc->blockNum;
00534 node->u.dir.father = father;
00535 node->u.dir.serial = serial;
00536
00537
00538 node->u.dir.checkSum = bc->spares[0].tag.dataSum;
00539
00540 break;
00541 case UFFS_TYPE_FILE:
00542 node->u.file.block = bc->blockNum;
00543 node->u.file.father = father;
00544 node->u.file.serial = serial;
00545 node->u.file.checkSum = bc->spares[0].tag.dataSum;
00546 break;
00547 case UFFS_TYPE_DATA:
00548 node->u.data.block = bc->blockNum;
00549 node->u.data.father = father;
00550 node->u.data.serial = serial;
00551 break;
00552 default:
00553 uffs_Perror(UFFS_ERR_NOISY, PFX"Unknown type %d\n", type);
00554 break;
00555 }
00556
00557 uffs_InsertNodeToTree(dev, type, node);
00558 uffs_PutBlockInfo(dev, bc);
00559
00560 return U_SUCC;
00561 }
00562
00574 static URET _BufFlush_Exist_With_BlockCover(
00575 uffs_Device *dev,
00576 TreeNode *node,
00577 uffs_blockInfo *bc
00578 )
00579 {
00580 u16 i;
00581 u8 type, timeStamp;
00582 u16 page, father, serial;
00583 uffs_Buf *dirty, *buf;
00584 TreeNode *newNode;
00585 uffs_blockInfo *newBc;
00586 uffs_Tags *tag, *oldTag;
00587 URET ret = U_SUCC;
00588 u16 newBlock;
00589 UBOOL succRecover = U_TRUE;
00590
00591
00592 dirty = dev->buf.dirty;
00593 type = dirty->type;
00594 father = dirty->father;
00595 serial = dirty->serial;
00596
00597 newNode = uffs_GetErased(dev);
00598 if(newNode == NULL) {
00599 uffs_Perror(UFFS_ERR_NOISY, PFX"no enough erased block!\n");
00600 return U_FAIL;
00601 }
00602 newBlock = newNode->u.list.block;
00603 newBc = uffs_GetBlockInfo(dev, newBlock);
00604 if(newBc == NULL) {
00605 uffs_Perror(UFFS_ERR_SERIOUS, PFX"get block info fail!\n");
00606 uffs_InsertToErasedListHead(dev, newNode);
00607
00608 return U_FAIL;
00609 }
00610
00611 uffs_LoadBlockInfo(dev, newBc, UFFS_ALL_PAGES);
00612 timeStamp = uffs_GetNextBlockTimeStamp(uffs_GetBlockTimeStamp(dev, bc));
00613
00614
00615
00616
00617 for(i = 0; i < dev->attr.pages_per_block; i++) {
00618 tag = &(newBc->spares[i].tag);
00619 tag->blockTimeStamp = timeStamp;
00620 tag->father = father;
00621 tag->serial = serial;
00622 tag->type = type;
00623 tag->pageID = (u8)i;
00624
00625 buf = _FindBufInDirtyList(dirty, i);
00626 if(buf != NULL) {
00627 tag->dataLength = buf->dataLen;
00628 tag->dataSum = _GetDataSum(dev, buf);
00629 ret = uffs_WriteDataToNewPage(dev, newBlock, i, tag, buf);
00630 if(ret == U_SUCC) {
00631 if(_BreakFromDirty(dev, buf) == U_SUCC) {
00632 buf->mark = UFFS_BUF_VALID;
00633 _MoveNodeToHead(dev, buf);
00634 }
00635 }
00636 else{
00637 uffs_Perror(UFFS_ERR_NORMAL, PFX"I/O error <3>?\n");
00638 succRecover = U_FALSE;
00639 break;
00640 }
00641 }
00642 else {
00643
00644 page = uffs_FindPageInBlockWithPageId(dev, bc, i);
00645 if(page == UFFS_INVALID_PAGE) {
00646 uffs_ExpireBlockInfo(dev, newBc, i);
00647 break;
00648 }
00649 page = uffs_FindBestPageInBlock(dev, bc, page);
00650
00651 oldTag = &(bc->spares[page].tag);
00652 buf = uffs_BufClone(dev, NULL);
00653 if(buf == NULL) {
00654 uffs_Perror(UFFS_ERR_SERIOUS, PFX"Can't clone a new buf!\n");
00655 succRecover = U_FALSE;
00656 break;
00657 }
00658 ret = uffs_LoadPhiDataToBuf(dev, buf, bc->blockNum, page);
00659 if(ret == U_FAIL) {
00660 uffs_Perror(UFFS_ERR_SERIOUS, PFX"I/O error ?\n");
00661 uffs_BufFreeClone(dev, buf);
00662 break;
00663 }
00664 buf->dataLen = oldTag->dataLength;
00665 if(buf->dataLen > dev->com.pgDataSize) {
00666 uffs_Perror(UFFS_ERR_NOISY, PFX"data length over flow!!!\n");
00667 buf->dataLen = dev->com.pgDataSize;
00668 }
00669
00670 buf->type = type;
00671 buf->father = father;
00672 buf->serial = serial;
00673 buf->dataLen = oldTag->dataLength;
00674 buf->pageID = oldTag->pageID;
00675
00676 tag->dataLength = buf->dataLen;
00677 tag->dataSum = _GetDataSum(dev, buf);
00678
00679 ret = uffs_WriteDataToNewPage(dev, newBlock, i, tag, buf);
00680 uffs_BufFreeClone(dev, buf);
00681 if(ret != U_SUCC) {
00682 uffs_Perror(UFFS_ERR_NORMAL, PFX"I/O error <4>?\n");
00683 succRecover = U_FALSE;
00684 break;
00685 }
00686 }
00687
00688 }
00689
00690 if(succRecover == U_TRUE) {
00691 switch(type) {
00692 case UFFS_TYPE_DIR:
00693 node->u.dir.block = newBlock;
00694 node->u.dir.checkSum = newBc->spares[0].tag.dataSum;
00695
00696
00697 break;
00698 case UFFS_TYPE_FILE:
00699 node->u.file.block = newBlock;
00700 node->u.file.checkSum = newBc->spares[0].tag.dataSum;
00701 break;
00702 case UFFS_TYPE_DATA:
00703 node->u.data.block = newBlock;
00704 break;
00705 default:
00706 uffs_Perror(UFFS_ERR_SERIOUS, PFX"UNKNOW TYPE\n");
00707 break;
00708 }
00709 newNode->u.list.block = bc->blockNum;
00710 dev->ops->EraseBlock(dev, bc->blockNum);
00711 uffs_InsertToErasedListTail(dev, newNode);
00712 uffs_ExpireBlockInfo(dev, bc, UFFS_ALL_PAGES);
00713 }
00714 else {
00715 uffs_ExpireBlockInfo(dev, newBc, UFFS_ALL_PAGES);
00716 dev->ops->EraseBlock(dev, newBlock);
00717 newNode->u.list.block = newBlock;
00718 uffs_InsertToErasedListTail(dev, newNode);
00719 }
00720
00721 if(dev->buf.dirty != NULL || dev->buf.dirtyCount != 0) {
00722 uffs_Perror(UFFS_ERR_NORMAL, PFX"still has dirty buffer ?\n");
00723 }
00724
00725 uffs_PutBlockInfo(dev, newBc);
00726
00727 return U_SUCC;
00728 }
00729
00734 URET uffs_BufFlush(struct uffs_DeviceSt *dev)
00735 {
00736 uffs_Buf *dirty;
00737 TreeNode *node;
00738 uffs_blockInfo *bc;
00739 u16 n;
00740 URET ret;
00741 u8 type;
00742 u16 father;
00743 u16 serial;
00744 int block;
00745
00746 dirty = dev->buf.dirty;
00747 if(dirty == NULL || dev->buf.dirtyCount == 0) {
00748 return U_SUCC;
00749 }
00750
00751 if(_CheckDirtyList(dev) == U_FAIL) return U_FAIL;
00752
00753 type = dirty->type;
00754 father = dirty->father;
00755 serial = dirty->serial;
00756
00757 switch(type) {
00758 case UFFS_TYPE_DIR:
00759 node = uffs_FindDirNodeFromTree(dev, serial);
00760 break;
00761 case UFFS_TYPE_FILE:
00762 node = uffs_FindFileNodeFromTree(dev, serial);
00763 break;
00764 case UFFS_TYPE_DATA:
00765 node = uffs_FindDataNode(dev, father, serial);
00766 break;
00767 default:
00768 uffs_Perror(UFFS_ERR_SERIOUS, PFX"unknown type\n");
00769 return U_FAIL;
00770 }
00771
00772 if(node == NULL) {
00773
00774 ret = _BufFlush_NewBlock(dev);
00775 }
00776 else {
00777 switch(type) {
00778 case UFFS_TYPE_DIR:
00779 block = node->u.dir.block;
00780 break;
00781 case UFFS_TYPE_FILE:
00782 block = node->u.file.block;
00783 break;
00784 case UFFS_TYPE_DATA:
00785 block = node->u.data.block;
00786 break;
00787 }
00788 bc = uffs_GetBlockInfo(dev, block);
00789 if(bc == NULL) {
00790 uffs_Perror(UFFS_ERR_SERIOUS, PFX"get block info fail.\n");
00791 return U_FAIL;
00792 }
00793 uffs_LoadBlockInfo(dev, bc, UFFS_ALL_PAGES);
00794 n = uffs_GetFreePagesCount(dev, bc);
00795 if(n >= dev->buf.dirtyCount) {
00796
00797 ret = _BufFlush_Exist_With_Enough_FreePage(dev, bc, n);
00798 }
00799 else {
00800 ret = _BufFlush_Exist_With_BlockCover(dev, node, bc);
00801 }
00802 uffs_PutBlockInfo(dev, bc);
00803 }
00804
00805 return ret;
00806 }
00807
00808
00809
00818 uffs_Buf * uffs_BufGet(struct uffs_DeviceSt *dev, u16 father, u16 serial, u16 pageID)
00819 {
00820 uffs_Buf *p;
00821
00822
00823 p = uffs_BufFind(dev, father, serial, pageID);
00824
00825 if(p) {
00826 p->refCount++;
00827 _MoveNodeToHead(dev, p);
00828 }
00829
00830 return p;
00831 }
00832
00836 uffs_Buf *uffs_BufNew(struct uffs_DeviceSt *dev, u8 type, u16 father, u16 serial, u16 pageID)
00837 {
00838 uffs_Buf *buf;
00839
00840 buf = uffs_BufGet(dev, father, serial, pageID);
00841 if(buf) {
00842 uffs_Perror(UFFS_ERR_SERIOUS, PFX"Want to create a new buf, buf found in exist ???!!\n");
00843 return buf;
00844 }
00845
00846 buf = _FindFreeBuf(dev);
00847 if(buf == NULL) {
00848 uffs_BufFlush(dev);
00849 buf = _FindFreeBuf(dev);
00850 if (buf == NULL) {
00851 uffs_Perror(UFFS_ERR_SERIOUS, PFX"no free page buf!\n");
00852 return NULL;
00853 }
00854 }
00855
00856 buf->mark = UFFS_BUF_EMPTY;
00857 buf->type = type;
00858 buf->father = father;
00859 buf->serial = serial;
00860 buf->pageID = pageID;
00861 buf->dataLen = 0;
00862 buf->refCount++;
00863 memset(buf->data, 0xff, dev->com.pgSize);
00864
00865 _MoveNodeToHead(dev, buf);
00866
00867 return buf;
00868 }
00869
00870
00871
00882 uffs_Buf *uffs_BufGetEx(struct uffs_DeviceSt *dev, u8 type, TreeNode *node, u16 pageID)
00883 {
00884 uffs_Buf *buf;
00885 u16 father, serial, block, page;
00886 uffs_blockInfo *bc;
00887
00888 switch(type) {
00889 case UFFS_TYPE_DIR:
00890 father = node->u.dir.father;
00891 serial = node->u.dir.serial;
00892 block = node->u.dir.block;
00893 break;
00894 case UFFS_TYPE_FILE:
00895 father = node->u.file.father;
00896 serial = node->u.file.serial;
00897 block = node->u.file.block;
00898 break;
00899 case UFFS_TYPE_DATA:
00900 father = node->u.data.father;
00901 serial = node->u.data.serial;
00902 block = node->u.data.block;
00903 break;
00904 }
00905
00906 buf = uffs_BufFind(dev, father, serial, pageID);
00907 if(buf) {
00908 buf->refCount++;
00909 return buf;
00910 }
00911
00912 buf = _FindFreeBuf(dev);
00913 if(buf == NULL) {
00914 uffs_BufFlush(dev);
00915 buf = _FindFreeBuf(dev);
00916 if (buf == NULL) {
00917 uffs_Perror(UFFS_ERR_SERIOUS, PFX"no free page buf!\n");
00918 return NULL;
00919 }
00920 }
00921
00922 bc = uffs_GetBlockInfo(dev, block);
00923 if (bc == NULL) {
00924 uffs_Perror(UFFS_ERR_SERIOUS, PFX"Can't get block info!\n");
00925 return NULL;
00926 }
00927
00928 page = uffs_FindPageInBlockWithPageId(dev, bc, pageID);
00929 if(page == UFFS_INVALID_PAGE) {
00930 uffs_PutBlockInfo(dev, bc);
00931 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't find right page ?\n");
00932 return NULL;
00933 }
00934 page = uffs_FindBestPageInBlock(dev, bc, page);
00935 uffs_PutBlockInfo(dev, bc);
00936
00937 buf->mark = UFFS_BUF_EMPTY;
00938 buf->type = type;
00939 buf->father = father;
00940 buf->serial = serial;
00941 buf->pageID = pageID;
00942
00943 if (uffs_LoadPhiDataToBuf(dev, buf, block, page) == U_FAIL) {
00944 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't load page from flash !\n");
00945 return NULL;
00946 }
00947
00948 buf->dataLen = bc->spares[page].tag.dataLength;
00949 buf->mark = UFFS_BUF_VALID;
00950 buf->refCount++;
00951
00952 _MoveNodeToHead(dev, buf);
00953
00954 return buf;
00955
00956 }
00957
00963 URET uffs_BufPut(uffs_Device *dev, uffs_Buf *buf)
00964 {
00965 if(buf == NULL) {
00966 uffs_Perror(UFFS_ERR_NORMAL, PFX "Can't put an NULL buffer!\n");
00967 return U_FAIL;
00968 }
00969 if(buf->refCount == 0) {
00970 uffs_Perror(UFFS_ERR_NORMAL, PFX "Putting an unused page buffer ? \n");
00971 return U_FAIL;
00972 }
00973
00974 buf->refCount--;
00975
00976 return U_SUCC;
00977 }
00978
00979
00990 uffs_Buf * uffs_BufClone(uffs_Device *dev, uffs_Buf *buf)
00991 {
00992 uffs_Buf *p;
00993
00994 p = _FindFreeBuf(dev);
00995 if(p == NULL) {
00996 uffs_Perror(UFFS_ERR_SERIOUS, PFX"no enough free pages for clone!\n");
00997 return NULL;
00998 }
00999 _BreakFromBufList(dev, p);
01000
01001 if(buf) {
01002 p->father = buf->father;
01003 p->type = buf->type;
01004 p->serial = buf->serial;
01005 p->pageID = buf->pageID;
01006
01007 p->dataLen = buf->dataLen;
01008
01009
01010 memcpy(p->data, buf->data, dev->com.pgSize);
01011 }
01012 p->next = p->prev = NULL;
01013 p->nextDirty = p->prevDirty = NULL;
01014 p->refCount = CLONE_BUF_MARK;
01015 return p;
01016 }
01017
01023 void uffs_BufFreeClone(uffs_Device *dev, uffs_Buf *buf)
01024 {
01025 dev = dev;
01026 if(!buf) return;
01027
01028 if(buf->refCount != CLONE_BUF_MARK) {
01029
01030 uffs_Perror(UFFS_ERR_SERIOUS, PFX "Try to release a non-cloned page buffer ?\n");
01031 return;
01032 }
01033 buf->refCount = 0;
01034 buf->mark = UFFS_BUF_EMPTY;
01035 _LinkToBufListTail(dev, buf);
01036 }
01037
01038
01039
01040 UBOOL uffs_BufIsAllFree(struct uffs_DeviceSt *dev)
01041 {
01042 uffs_Buf *buf = dev->buf.bufHead;
01043 while(buf) {
01044 if(buf->refCount != 0) return U_FALSE;
01045 buf = buf->next;
01046 }
01047 return U_TRUE;
01048 }
01049
01050 UBOOL uffs_BufIsAllEmpty(struct uffs_DeviceSt *dev)
01051 {
01052 uffs_Buf *buf = dev->buf.bufHead;
01053 while(buf) {
01054 if(buf->mark != UFFS_BUF_EMPTY) return U_FALSE;
01055 buf = buf->next;
01056 }
01057 return U_TRUE;
01058 }
01059
01060
01061 URET uffs_BufSetAllEmpty(struct uffs_DeviceSt *dev)
01062 {
01063 uffs_Buf *buf = dev->buf.bufHead;
01064 while(buf) {
01065 buf->mark = UFFS_BUF_EMPTY;
01066 buf = buf->next;
01067 }
01068 return U_SUCC;
01069 }
01070
01071
01072 void uffs_BufIncRef(uffs_Buf *buf)
01073 {
01074 buf->refCount++;
01075 }
01076
01077 void uffs_BufDecRef(uffs_Buf *buf)
01078 {
01079 if(buf->refCount > 0) buf->refCount--;
01080 }
01081
01082 void uffs_BufSetMark(uffs_Buf *buf, int mark)
01083 {
01084 buf->mark = mark;
01085 }
01086
01087 static UBOOL _IsBufInDirtyList(struct uffs_DeviceSt *dev, uffs_Buf *buf)
01088 {
01089 uffs_Buf *p = dev->buf.dirty;
01090 while(p) {
01091 if(p == buf) return U_TRUE;
01092 p = p->nextDirty;
01093 }
01094 return U_FALSE;
01095 }
01096
01097 URET uffs_BufWrite(struct uffs_DeviceSt *dev, uffs_Buf *buf, void *data, u32 ofs, u32 len)
01098 {
01099 uffs_Buf *dirty;
01100 UBOOL inDirtyList = U_FALSE;
01101
01102 if(ofs + len > dev->com.pgDataSize) {
01103 uffs_Perror(UFFS_ERR_SERIOUS, PFX"data length out of range! %d+%d\n", ofs, len);
01104 return U_FAIL;
01105 }
01106
01107 if(dev->buf.dirtyCount > 0) {
01108 dirty = dev->buf.dirty;
01109 inDirtyList = _IsBufInDirtyList(dev, buf);
01110
01111 if(inDirtyList == U_FALSE) {
01112
01113
01114 if(dirty->father != buf->father ||
01115 dirty->serial != buf->serial ||
01116 dirty->type != buf->type) {
01117
01118 if(uffs_BufFlush(dev) != U_SUCC) return U_FAIL;
01119 }
01120 }
01121 }
01122
01123 memcpy(buf->data + ofs, data, len);
01124 if(ofs + len > buf->dataLen) buf->dataLen = ofs + len;
01125
01126 if(inDirtyList == U_FALSE) {
01127 _LinkToDirtyList(dev, buf);
01128 }
01129
01130 if(dev->buf.dirtyCount >= dev->buf.maxDirtyBuf) {
01131 if(uffs_BufFlush(dev) != U_SUCC) {
01132 return U_FAIL;
01133 }
01134 }
01135
01136 return U_SUCC;
01137 }
01138
01139 URET uffs_BufRead(struct uffs_DeviceSt *dev, uffs_Buf *buf, void *data, u32 ofs, u32 len)
01140 {
01141 u32 readSize;
01142 u32 pgDataSize = dev->com.pgDataSize;
01143
01144 readSize = (ofs >= pgDataSize ? 0 : (ofs + len >= pgDataSize ? pgDataSize - ofs : len));
01145 if(readSize > 0) memcpy(data, buf->data + ofs, readSize);
01146
01147 return U_SUCC;
01148 }
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161