⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uffs_buf.c~

📁 nandflash文件系统源代码
💻 C~
📖 第 1 页 / 共 3 页
字号:
			block = node->u.file.block;
			break;
		case UFFS_TYPE_DATA:
			block = node->u.data.block;
			break;
		default:
			uffs_Perror(UFFS_ERR_SERIOUS, PFX"unknown type.\n");
			return U_FAIL;
		}
		bc = uffs_GetBlockInfo(dev, block);
		if(bc == NULL) {
			uffs_Perror(UFFS_ERR_SERIOUS, PFX"get block info fail.\n");
			return U_FAIL;
		}
		uffs_LoadBlockInfo(dev, bc, UFFS_ALL_PAGES);
		n = uffs_GetFreePagesCount(dev, bc);

		if(n >= dev->buf.dirtyCount && !force_block_recover) {
			//The free pages are enough for the dirty pages
			ret = _BufFlush_Exist_With_Enough_FreePage(dev, bc, n);
		}
		else {
			ret = _BufFlush_Exist_With_BlockCover(dev, node, bc);
		}
		uffs_PutBlockInfo(dev, bc);
	}

	return ret;
}

/** 
 * flush buffers to flash
 * \param[in] dev uffs device
 */
URET uffs_BufFlush(struct uffs_DeviceSt *dev)
{
	return _BufFlush(dev, U_FALSE);
}

/** 
 * flush buffers to flash
 * \param[in] dev uffs device
 * \param[in] force_block_recover #U_TRUE: force a block recover even there are enough free pages
 */
URET uffs_BufFlushEx(struct uffs_DeviceSt *dev, UBOOL force_block_recover)
{
	return _BufFlush(dev, force_block_recover);
}


/** 
 * \brief get a page buffer
 * \param[in] dev uffs device
 * \param[in] father father serial num
 * \param[in] serial serial num
 * \param[in] pageID pageID
 * \return return the buffer found in buffer list, if not found, return NULL.
 */
uffs_Buf * uffs_BufGet(struct uffs_DeviceSt *dev, u16 father, u16 serial, u16 pageID)
{
	uffs_Buf *p;

	//first, check whether the buffer exist in buf list ?
	p = uffs_BufFind(dev, father, serial, pageID);

	if(p) {
		p->refCount++;
		_MoveNodeToHead(dev, p);
	}

	return p;
}

/** 
 * New generate a buffer
 */
uffs_Buf *uffs_BufNew(struct uffs_DeviceSt *dev, u8 type, u16 father, u16 serial, u16 pageID)
{
	uffs_Buf *buf;

	buf = uffs_BufGet(dev, father, serial, pageID);
	if (buf) {
		if (buf->refCount > 1) {
			uffs_Perror(UFFS_ERR_SERIOUS, PFX"When create new buf, an exist buffer has ref count %d, possibly bug!\n", buf->refCount);
		}
		else {
			buf->dataLen = 0;
		}
		_MoveNodeToHead(dev, buf);
		return buf;
	}

	buf = _FindFreeBuf(dev);
	if(buf == NULL) {
		uffs_BufFlush(dev);
		buf = _FindFreeBuf(dev);
		if (buf == NULL) {
			uffs_Perror(UFFS_ERR_SERIOUS, PFX"no free page buf!\n");
			return NULL;
		}
	}

	buf->mark = UFFS_BUF_EMPTY;
	buf->type = type;
	buf->father = father;
	buf->serial = serial;
	buf->pageID = pageID;
	buf->dataLen = 0;
	buf->refCount++;
	memset(buf->data, 0xff, dev->com.pgSize);

	_MoveNodeToHead(dev, buf);
	
	return buf;	
}



/** 
 * get a page buffer
 * \param[in] dev uffs device
 * \param[in] type dir, file or data ?
 * \param[in] node node on the tree
 * \param[in] pageID pageID
 * \return return the bufer if found in buffer list, if not found in 
 *			buffer list, it will get a free buffer, and load data from flash.
 *			return NULL if not free buffer.
 */
uffs_Buf *uffs_BufGetEx(struct uffs_DeviceSt *dev, u8 type, TreeNode *node, u16 pageID)
{
	uffs_Buf *buf;
	u16 father, serial, block, page;
	uffs_blockInfo *bc;

	switch(type) {
	case UFFS_TYPE_DIR:
		father = node->u.dir.father;
		serial = node->u.dir.serial;
		block = node->u.dir.block;
		break;
	case UFFS_TYPE_FILE:
		father = node->u.file.father;
		serial = node->u.file.serial;
		block = node->u.file.block;
		break;
	case UFFS_TYPE_DATA:
		father = node->u.data.father;
		serial = node->u.data.serial;
		block = node->u.data.block;
		break;
	default:
		uffs_Perror(UFFS_ERR_SERIOUS, PFX"unknown type");
		return NULL;
	}

	buf = uffs_BufFind(dev, father, serial, pageID);
	if(buf) {
		buf->refCount++;
		return buf;
	}

	buf = _FindFreeBuf(dev);
	if(buf == NULL) {
		uffs_BufFlush(dev);
		buf = _FindFreeBuf(dev);
		if (buf == NULL) {
			uffs_Perror(UFFS_ERR_SERIOUS, PFX"no free page buf!\n");
			return NULL;
		}
	}

	bc = uffs_GetBlockInfo(dev, block);
	if (bc == NULL) {
		uffs_Perror(UFFS_ERR_SERIOUS, PFX"Can't get block info!\n");
		return NULL;
	}
	
	page = uffs_FindPageInBlockWithPageId(dev, bc, pageID);
	if(page == UFFS_INVALID_PAGE) {
		uffs_PutBlockInfo(dev, bc);
		uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't find right page ?\n");
		return NULL;
	}
	page = uffs_FindBestPageInBlock(dev, bc, page);
	uffs_PutBlockInfo(dev, bc);

	buf->mark = UFFS_BUF_EMPTY;
	buf->type = type;
	buf->father = father;
	buf->serial = serial;
	buf->pageID = pageID;

	if (uffs_LoadPhiDataToBuf(dev, buf, block, page) == U_FAIL) {
		uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't load page from flash !\n");
		return NULL;
	}

	buf->dataLen = bc->spares[page].tag.dataLength;
	buf->mark = UFFS_BUF_VALID;
	buf->refCount++;

	_MoveNodeToHead(dev, buf);
	
	return buf;

}

/** 
 * \brief Put back a page buffer, make reference count decrease by one
 * \param[in] dev uffs device
 * \param[in] buf buffer to be put back
 */
URET uffs_BufPut(uffs_Device *dev, uffs_Buf *buf)
{
	dev = dev;
	if(buf == NULL) {
		uffs_Perror(UFFS_ERR_NORMAL, PFX "Can't put an NULL buffer!\n");
		return U_FAIL;
	}
	if(buf->refCount == 0) {
		uffs_Perror(UFFS_ERR_NORMAL, PFX "Putting an unused page buffer ? \n");
		return U_FAIL;
	}

	buf->refCount--;
	
	return U_SUCC;
}


/** 
 * \brief clone from an exist buffer.
		allocate memory for new buffer, and copy data from original buffer if 
		original buffer is not NULL. 
 * \param[in] dev uffs device
 * \param[in] buf page buffer to be clone from. if NULL presented here, data copy will not be processed
 * \return return the cloned page buffer, all data copied from source
 * \note the cloned buffer is not linked in page buffer list in uffs device,
 *			so you should use #uffs_BufFreeClone instead of #uffs_BufPut when you put back or release buffer
 */
uffs_Buf * uffs_BufClone(uffs_Device *dev, uffs_Buf *buf)
{
	uffs_Buf *p;

	p = _FindFreeBuf(dev);
	if(p == NULL) {
		uffs_Perror(UFFS_ERR_SERIOUS, PFX"no enough free pages for clone!\n");
		return NULL;
	}
	_BreakFromBufList(dev, p);

	if(buf) {
		p->father = buf->father;
		p->type = buf->type;
		p->serial = buf->serial;
		p->pageID = buf->pageID;
		
		p->dataLen = buf->dataLen;
		//athough the valid data length is .dataLen,
		//but we still need copy the whole buffer, include ecc
		memcpy(p->data, buf->data, dev->com.pgSize);
	}
	p->next = p->prev = NULL;			//because the cloned one is not linked to device buffer
	p->nextDirty = p->prevDirty = NULL;
	p->refCount = CLONE_BUF_MARK;		//CLONE_BUF_MARK indicates that this is an cloned buffer
	return p;
}

/** 
 * \brief release cloned buffer
 * \param[in] dev uffs device
 * \param[in] buf cloned buffer
 */
void uffs_BufFreeClone(uffs_Device *dev, uffs_Buf *buf)
{
	dev = dev; //make compiler happy
	if(!buf) return;

	if(buf->refCount != CLONE_BUF_MARK) {
		/* a cloned buffer must have a refCount of CLONE_BUF_MARK */
		uffs_Perror(UFFS_ERR_SERIOUS, PFX "Try to release a non-cloned page buffer ?\n");
		return;
	}
	buf->refCount = 0;
	buf->mark = UFFS_BUF_EMPTY;
	_LinkToBufListTail(dev, buf);
}



UBOOL uffs_BufIsAllFree(struct uffs_DeviceSt *dev)
{
	uffs_Buf *buf = dev->buf.bufHead;
	while(buf) {
		if(buf->refCount != 0) return U_FALSE;
		buf = buf->next;
	}
	return U_TRUE;
}

UBOOL uffs_BufIsAllEmpty(struct uffs_DeviceSt *dev)
{
	uffs_Buf *buf = dev->buf.bufHead;
	while(buf) {
		if(buf->mark != UFFS_BUF_EMPTY) return U_FALSE;
		buf = buf->next;
	}
	return U_TRUE;
}


URET uffs_BufSetAllEmpty(struct uffs_DeviceSt *dev)
{
	uffs_Buf *buf = dev->buf.bufHead;
	while(buf) {
		buf->mark = UFFS_BUF_EMPTY;
		buf = buf->next;
	}
	return U_SUCC;
}


void uffs_BufIncRef(uffs_Buf *buf)
{
	buf->refCount++;
}

void uffs_BufDecRef(uffs_Buf *buf)
{
	if(buf->refCount > 0) buf->refCount--;
}

void uffs_BufSetMark(uffs_Buf *buf, int mark)
{
	buf->mark = mark;
}

static UBOOL _IsBufInDirtyList(struct uffs_DeviceSt *dev, uffs_Buf *buf)
{
	uffs_Buf *p = dev->buf.dirty;
	while(p) {
		if(p == buf) return U_TRUE;
		p = p->nextDirty;
	}
	return U_FALSE;
}

URET uffs_BufWrite(struct uffs_DeviceSt *dev, uffs_Buf *buf, void *data, u32 ofs, u32 len)
{
	uffs_Buf *dirty;
	UBOOL inDirtyList = U_FALSE;

	if(ofs + len > dev->com.pgDataSize) {
		uffs_Perror(UFFS_ERR_SERIOUS, PFX"data length out of range! %d+%d\n", ofs, len);
		return U_FAIL;
	}

	if(dev->buf.dirtyCount > 0) {
		dirty = dev->buf.dirty;
		inDirtyList = _IsBufInDirtyList(dev, buf);

		if(inDirtyList == U_FALSE) {
			//new dirty buffer...
			
			if(dirty->father != buf->father ||
				dirty->serial != buf->serial ||
				dirty->type != buf->type) {
				//new buf is in different block, flush buffer right now
				if(uffs_BufFlush(dev) != U_SUCC) return U_FAIL;
			}
		}
	}

	memcpy(buf->data + ofs, data, len);
	if(ofs + len > buf->dataLen) buf->dataLen = ofs + len;
	
	if(inDirtyList == U_FALSE) {
		_LinkToDirtyList(dev, buf);
	}

	if(dev->buf.dirtyCount >= dev->buf.maxDirtyBuf) {
		if(uffs_BufFlush(dev) != U_SUCC) {
			return U_FAIL;
		}
	}

	return U_SUCC;
}

URET uffs_BufRead(struct uffs_DeviceSt *dev, uffs_Buf *buf, void *data, u32 ofs, u32 len)
{
	u32 readSize;
	u32 pgDataSize = dev->com.pgDataSize;

	readSize = (ofs >= pgDataSize ? 0 :	(ofs + len >= pgDataSize ? pgDataSize - ofs : len));
	if(readSize > 0) memcpy(data, buf->data + ofs, readSize);

	return U_SUCC;
}







⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -