提交 8d77fe70 编写于 作者: I iamyhw@gmail.com

fixed bug: no release uffs_object_handler in dfs_uffs.c

function:dfs_uffs_open()

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1363 bbd45198-f89e-11dd-88c7-29a3b14d5316
上级 ccf7d679
......@@ -10,6 +10,7 @@
* \file nand flash interface example
* \brief example for using nand flash driver and multiple partitions, with system memory allocator.
* \author Ricky Zheng, created at 27 Nov, 2007
* \modify amsl, at 17 Jan, 2010 iamyhw@gmail.com
*/
#include <rtthread.h>
......@@ -88,40 +89,42 @@ static int nand_is_badblock(uffs_Device *dev,u32 block)
return K9F2G08_Check_badblk(block);
}
/* The only uffs v1.3.2-4 can used. */
static uffs_FlashOps nand_driver_ops =
{
nand_read_page_data, //ReadPageData
nand_read_page_spare, //ReadPageSpare
NULL, //ReadPageSpareWithLayout
nand_write_page_data, //WritePageData
nand_write_page_spare, //WritePageSpare
NULL, //WriteFullPage
nand_is_badblock, //IsBadBlock
nand_mark_badblock, //MarkBadBlock
nand_erase_block, //EraseBlock
nand_read_page_data, /* ReadPageData */
nand_read_page_spare, /* ReadPageSpare */
NULL, /* ReadPageSpareWithLayout */
nand_write_page_data, /* WritePageData */
nand_write_page_spare, /* WritePageSpare */
NULL, /* WriteFullPage */
nand_is_badblock, /* IsBadBlock */
nand_mark_badblock, /* MarkBadBlock */
nand_erase_block, /* EraseBlock */
};
//change these parameters to fit your nand flash specification
//#define MAN_ID MAN_ID_SAMSUNG // simulate Samsung's NAND flash
static struct uffs_StorageAttrSt flash_storage = {0};
static int initDevice(uffs_Device *dev)
{
dev->ops = &nand_driver_ops;
return RT_EOK;
return U_SUCC;
}
static int releaseDevice(uffs_Device *dev)
{
return RT_EOK;
return U_SUCC;
}
#include <dfs_uffs.h>
static uffs_Device uffs_device = {0};
/* define mount table,UFFS FS private data */
/* it is absolute accessing for uffs.*/
/*
* define mount table,UFFS FS private data
* it is absolute accessing for uffs.
* set struct data on the RT-Thread device
*/
static uffs_MountTable uffs_mount_table =
{
&uffs_device,
......@@ -175,40 +178,42 @@ struct nand_flash_dev* nand_init(u8* buf)
return RT_NULL;
}
/* RT-Thread Device Driver Interface */
/* UFFS FileSystem NandFlash InterFace */
/* we don't use entity, let uffs autarky */
/*
* RT-Thread Device Driver Interface
* UFFS FileSystem NandFlash InterFace
* we don't use entity, let uffs autarky
*/
struct rt_device nand_device;
static rt_err_t rt_nand_init(rt_device_t dev)
{
return 0;
return RT_EOK;
}
static rt_err_t rt_nand_open(rt_device_t dev, u16 oflag)
{
return 0;
return RT_EOK;
}
static rt_err_t rt_nand_close(rt_device_t dev)
{
return 0;
return RT_EOK;
}
static rt_err_t rt_nand_control(rt_device_t dev, u8 cmd, void *args)
{
return 0;
return RT_EOK;
}
static rt_size_t rt_nand_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
return 0;
return RT_EOK;
}
static rt_size_t rt_nand_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
return 0;
return RT_EOK;
}
void rt_hw_nand_init(void)
......@@ -236,7 +241,7 @@ void rt_hw_nand_init(void)
/* about uffs codes */
entry = &uffs_mount_table;
//entry->lock = rt_sem_create("sem_nand0", 1, RT_IPC_FLAG_FIFO);//??it's lonely!how to do?
/* entry->lock = rt_sem_create("sem_nand0", 1, RT_IPC_FLAG_FIFO); */ /* it's lonely!how to do? */
uffs_MemSetupSystemAllocator(&(entry->dev->mem));
entry->dev->Init = initDevice;
......@@ -261,7 +266,7 @@ void rt_hw_nand_init(void)
extid >>= 2;
/* Calc blocksize. Blocksize is multiples of 64KiB */
chip->pages_per_block = ((64*1024)<<(extid & 0x03))/(chip->page_data_size);
/* The 5th id byte */
/* The 5th id byte,it is no use */
chip->total_blocks = (type->chipsize*1024*1024) /
chip->page_data_size / chip->pages_per_block;
......@@ -279,7 +284,7 @@ void rt_hw_nand_init(void)
chip->block_status_offs = NAND_SMALL_BADBLOCK_POS;
chip->ecc_opt = UFFS_ECC_SOFT; /* ecc option, do not use ECC,debug */
chip->layout_opt = UFFS_LAYOUT_UFFS; /* let UFFS do the spare layout */
#if (0) //DEBUG trace facility
#if (0) /* DEBUG trace facility */
rt_kprintf("page_data_size = %d\n",chip->page_data_size);
rt_kprintf("pages_per_block = %d\n",chip->pages_per_block);
rt_kprintf("spare_size = %d\n",chip->spare_size);
......@@ -289,5 +294,5 @@ void rt_hw_nand_init(void)
}
}
//end of file
/* end of file */
......@@ -37,36 +37,46 @@ int dfs_uffs_statfs(struct dfs_filesystem* fs, struct statfs *buf)
}
int dfs_uffs_open(struct dfs_fd* fd)
{
int ret=U_SUCC;
{
if (fd->flags & DFS_O_DIRECTORY)
{//ļ
uffs_DIR *dirp;
/* open directory */
{ /* directory */
uffs_DIR* dirp;
int oflag = UO_DIR;
if (fd->flags & DFS_O_CREAT) oflag |= UO_CREATE;
if (fd->flags & DFS_O_RDONLY) oflag |= UO_RDONLY;
if (fd->flags & DFS_O_WRONLY) oflag |= UO_WRONLY;
if (fd->flags & DFS_O_CREAT)
{//
ret = uffs_open(fd->path,UO_CREATE|UO_DIR);
if(ret != U_SUCC)
if (oflag & UO_CREATE)
{ /* create directory right now */
uffs_Object* fp = uffs_GetObject();
if(fp == NULL)
{
uffs_set_error(-UEMFILE);
return U_FAIL;
}
if(uffs_OpenObject(fp, fd->path, oflag) != U_SUCC)
{
return U_FAIL;
}
/* release object hander */
uffs_PutObject(fp);
}
/* use directory handler */
dirp = uffs_opendir(fd->path);
if(dirp == NULL)
{
uffs_set_error(-UEMFILE);
ret = U_FAIL;
return U_FAIL;
}
fd->data = dirp;
return U_SUCC;
}
else
{/
{/* file */
uffs_Object *fp;
int mode = UO_RDONLY;
......@@ -80,17 +90,15 @@ int dfs_uffs_open(struct dfs_fd* fd)
/* Creates a new file. The function fails if the file is already existing. */
if (fd->flags & DFS_O_EXCL) mode |= UO_EXCL;
/* allocate a fd */
/* open directory */
/* get an object hander */
fp = uffs_GetObject();
if(fp == NULL)
{
uffs_set_error(-UEMFILE);
ret = U_FAIL;
return U_FAIL;
}
if(uffs_OpenObject(fp, fd->path, mode) == RT_EOK)
if(uffs_OpenObject(fp, fd->path, mode) == U_SUCC)
{
struct uffs_stat stat_buf;
......@@ -104,20 +112,20 @@ int dfs_uffs_open(struct dfs_fd* fd)
{
fd->pos = uffs_SeekObject(fp, 0, USEEK_END);
}
ret = U_SUCC;
return U_SUCC;
}
else
{
/* open failed, return */
uffs_set_error(-uffs_GetObjectErr(fp));
/* release object hander */
uffs_PutObject(fp);
return U_FAIL;
}
}
return ret;
}
}
int dfs_uffs_close(struct dfs_fd* fd)
{
int ret=U_SUCC;
......@@ -125,21 +133,18 @@ int dfs_uffs_close(struct dfs_fd* fd)
if (fd->type == FT_DIRECTORY)
{
uffs_DIR* dirp;
dirp = (uffs_DIR*)(fd->data);
RT_ASSERT(dirp != RT_NULL);
uffs_closedir(dirp);
ret = uffs_closedir(dirp);
}
else if (fd->type == FT_REGULAR)
{
uffs_Object* fp;
fp = (uffs_Object*)(fd->data);
uffs_Object* fp = (uffs_Object*)(fd->data);
RT_ASSERT(fd != RT_NULL);
ret = uffs_CloseObject(fp);
/* release object hander */
uffs_PutObject(fp);
}
......@@ -169,7 +174,7 @@ int dfs_uffs_read(struct dfs_fd* fd, void* buf, rt_size_t count)
RT_ASSERT(fd != RT_NULL);
/* update position */
fd->pos = fp->pos;
fp->pos = fd->pos;
return uffs_ReadObject(fp, buf, count);
}
......@@ -179,7 +184,7 @@ int dfs_uffs_write(struct dfs_fd* fd, const void* buf, rt_size_t count)
uffs_Object* fp;
u32 byte_write;
struct uffs_stat stat_buf;
rt_kprintf("count=%d\n",count);
if(fd->type == FT_DIRECTORY)
{
return -DFS_STATUS_EISDIR;
......@@ -226,6 +231,11 @@ int dfs_uffs_getdents(struct dfs_fd* fd, struct dirent* dir, rt_uint32_t count)
rt_uint32_t index;
struct dirent* d;
if(fd->type != FT_DIRECTORY)
{
return -DFS_STATUS_EISDIR;
}
dirp = (uffs_DIR*)(fd->data);
RT_ASSERT(dirp != RT_NULL);
......@@ -276,18 +286,25 @@ int dfs_uffs_stat(struct dfs_filesystem* fs, const char* path, struct stat* st)
if (ret == U_SUCC)
{
st->st_dev = 0;
//st->st_mode = stat_buf.st_mode;
rt_uint32_t mode=0;
st->st_dev = 0;
st->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH |
DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH;
if (stat_buf.st_mode & US_IFDIR)
{
st->st_mode &= ~DFS_S_IFREG;
st->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH;
}
if (stat_buf.st_mode & US_IREAD)
st->st_mode &= ~(DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH);
if(stat_buf.st_mode & US_IFREG) mode |= DFS_S_IFREG;
if(stat_buf.st_mode & US_IFDIR) mode |= DFS_S_IFDIR;
if(stat_buf.st_mode & US_IRWXU) mode |= DFS_S_IRWXU;
if(stat_buf.st_mode & US_IRUSR) mode |= DFS_S_IRUSR;
if(stat_buf.st_mode & US_IWUSR) mode |= DFS_S_IWUSR;
if(stat_buf.st_mode & US_IXUSR) mode |= DFS_S_IXUSR;
if(stat_buf.st_mode & US_IRWXG) mode |= DFS_S_IRWXG;
if(stat_buf.st_mode & US_IRGRP) mode |= DFS_S_IRGRP;
if(stat_buf.st_mode & US_IWGRP) mode |= DFS_S_IWGRP;
if(stat_buf.st_mode & US_IXGRP) mode |= DFS_S_IXGRP;
if(stat_buf.st_mode & US_IRWXO) mode |= DFS_S_IRWXO;
if(stat_buf.st_mode & US_IROTH) mode |= DFS_S_IROTH;
if(stat_buf.st_mode & US_IWOTH) mode |= DFS_S_IWOTH;
if(stat_buf.st_mode & US_IXOTH) mode |= DFS_S_IXOTH;
st->st_mode = mode;
st->st_size = stat_buf.st_size;
st->st_mtime= stat_buf.st_mtime;
st->st_blksize= stat_buf.st_blksize;
......
......@@ -2,6 +2,7 @@
#define __K9F2G08_H__
#include <rtdef.h>
#include <s3c24x0.h>
#include <nand.h>
void K9F2G08_Program(u32 blockIndex, u32 srcAddress, u32 fileSize);
......
/**
* 用户要自己实现这个文件中的接口函数,不一样的芯片会有不同的访问命令
* 这个例程文件是关于Samsung k9f2g08芯片的,属于大页nandflash
/*
* uffs/flash/k9f2g08.c
*
* COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Info:
* Low hardware driver for samsung nandflash.
*/
/* XXX UFFS XXX */
#include <uffs/uffs_types.h>
#include <nand.h>
#include "s3c24x0.h"
#include <k9f2g08.h>
#define nand_write_cmd(cmd) (NFCMD = (cmd))
......@@ -17,51 +28,34 @@
#define nand_wait() {while(!(NFSTAT&(1<<0)));} //wait tWB and check F_RNB pin.
//NAND Flash Command.support K9F2G08
#define K9F2G08_CMD_READ0 0x00 // Read0
//#define K9F2G08_CMD_READ1 1 // Read1,K9F2G08 don't support the command.
#define K9F2G08_CMD_RANDOM_DATA_OUT 0x05 // Random data output
#define K9F2G08_CMD_PAGEPROG 0x10 // Write phase 2
#define K9F2G08_CMD_READ30 0x30 // Read30
#define K9F2G08_CMD_READ35 0x35 // Read35
//#define K9F2G08_CMD_READOOB 0x50 // Read oob
#define K9F2G08_CMD_ERASE1 0x60 // Erase phase 1
#define K9F2G08_CMD_STATUS 0x70 // Status read
#define K9F2G08_CMD_READ_EDC 0x7b // Read EDC Status
#define K9F2G08_CMD_SEQIN 0x80 // Write phase 1
#define K9F2G08_CMD_RANDOM_DATA_IN 0x85 // Random data input Copy-Back Program(0x85,0x10)
#define K9F2G08_CMD_READID 0x90 // ReadID,all-purpose command
#define K9F2G08_CMD_ERASE2 0xd0 // Erase phase 2
#define K9F2G08_CMD_RESET 0xff // Reset
#define BAD_CHECK (0)
#define ECC_CHECK (0)
//*************************************************
//** H/W dependent functions **
//*************************************************
// HCLK=100Mhz
#define TACLS 1 //1clk(0ns)
#define TWRPH0 4 //3clk(25ns)
#define TWRPH1 0 //1clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns
int read_nand_stats(void) // R/B 未接好?
/*
*************************************************
** H/W dependent functions **
*************************************************
*/
/* HCLK=100Mhz */
#define TACLS 1 /* 1clk(0ns) */
#define TWRPH0 4 /* 3clk(25ns) */
#define TWRPH1 0 /* 1clk(10ns) */ /* TACLS+TWRPH0+TWRPH1>=50ns */
int read_nand_stats(void) /* R/B is fixed? */
{
u8 stat;
nand_write_cmd(K9F2G08_CMD_STATUS);//0x70
nand_write_cmd(NAND_CMD_STATUS);
stat = nand_read();//读出返回的数据
stat = nand_read();/* read byte */
if(stat&1) return 1; // I/O0=1失败
else return 0; // I/O0=0成功
if(stat&1) return 1; /* I/O0=1 successful */
else return 0; /* I/O0=0 unsuccessful */
}
//擦除一个块
//返回0,successful
//返回1,error
/*
*erase a block
*return 0,successful
*return 1,error
*/
int K9F2G08_EraseBlock(u32 block)
{
int stat;
......@@ -69,50 +63,55 @@ int K9F2G08_EraseBlock(u32 block)
nand_cs_en();
nand_write_cmd(K9F2G08_CMD_ERASE1); // Erase one block 1st command
nand_write_cmd(NAND_CMD_ERASE1); /* Erase one block 1st command */
nand_write_addr(_page&0xff); // Page number=0
nand_write_addr(_page&0xff); /* Page number=0 */
nand_write_addr((_page>>8)&0xff);
nand_write_addr((_page>>16)&0xff);
nand_write_cmd(K9F2G08_CMD_ERASE2); // Erase one blcok 2nd command
nand_write_cmd(NAND_CMD_ERASE2); /* Erase one blcok 2nd command */
nand_wait(); // Wait tBERS max 3ms.
nand_wait(); /* Wait tBERS max 3ms. */
stat = read_nand_stats();
nand_cs_ds();
return stat;
}
//return 1 if it's a bad block, 0 if it's good.
int K9F2G08_Check_badblk(u32 block) //0:bad,1:good
/*
* check block is bad?
* return 1 if it's a bad block, 0 if it's good.
*/
int K9F2G08_Check_badblk(u32 block)
{
u8 data;
u32 _page;//块的首页地址
u32 _page;/* frist page in block */
_page = block*PAGES_PER_BLOCK; // For 2'nd cycle I/O[7:5]
_page = block*PAGES_PER_BLOCK; /* For 2'nd cycle I/O[7:5] */
nand_cs_en();
nand_write_cmd(K9F2G08_CMD_READ0); // Spare array read command
nand_write_addr(PAGE_DATA_SIZE&0xff); // Read the mark of bad block in spare array(M addr=5)
nand_write_cmd(NAND_CMD_READ0); /* Spare array read command */
nand_write_addr(PAGE_DATA_SIZE&0xff); /* Read the mark of bad block in spare array(M addr=5) */
nand_write_addr((PAGE_DATA_SIZE>>8)&0xff);
nand_write_addr(_page&0xff); // The mark of bad block is in 0 page
nand_write_addr((_page>>8)&0xff); // For block number A[24:17]
nand_write_addr((_page>>16)&0xff); // For block number A[25]
nand_write_cmd(K9F2G08_CMD_READ30);
nand_write_addr(_page&0xff); /* The mark of bad block is in 0 page */
nand_write_addr((_page>>8)&0xff); /* For block number A[24:17] */
nand_write_addr((_page>>16)&0xff); /* For block number A[25] */
nand_write_cmd(NAND_CMD_READSTART);
nand_wait(); // Wait tR(max 12us)
nand_wait(); /* Wait tR(max 12us) */
data=nand_read();
nand_cs_ds();
if(data==0x00)
return 1;//坏块
return 1;/* bad */
else
return 0;//好块
return 0;/* good */
}
//return 0 if ok, 1:fail
/*
* mark a block is bad
* return 0 if ok, 1:fail
*/
int K9F2G08_Mark_badblk(u32 block)
{
u8 stat;
......@@ -120,20 +119,20 @@ int K9F2G08_Mark_badblk(u32 block)
nand_cs_en();
nand_write_cmd(K9F2G08_CMD_SEQIN); // Write 1st command
nand_write_cmd(NAND_CMD_SEQIN); /* Write 1st command */
nand_write_addr(PAGE_DATA_SIZE & 0xff); // The mark of bad block
nand_write_addr(PAGE_DATA_SIZE & 0xff);/* The mark of bad block */
nand_write_addr((PAGE_DATA_SIZE>>8)&0xff);
nand_write_addr(_page&0xff); // marked 5th spare array
nand_write_addr((_page>>8)&0xff); // in the 1st page.
nand_write_addr((_page>>16)&0xff); //
nand_write_addr(_page&0xff); /* marked 1th spare array */
nand_write_addr((_page>>8)&0xff); /* in the 1st page. */
nand_write_addr((_page>>16)&0xff);
nand_write(0x00); //坏块标记
nand_write(0x00); /* 0x00 is commendatory make of the bad block. */
nand_write_cmd(K9F2G08_CMD_PAGEPROG); // Write 2nd command
nand_write_cmd(NAND_CMD_PAGEPROG); /* Write 2nd command */
nand_wait(); // Wait tPROG(200~500us)
stat = read_nand_stats();//查询是否成功
nand_wait(); /* Wait tPROG(200~500us) */
stat = read_nand_stats();
nand_cs_ds();
return stat;
......@@ -145,23 +144,23 @@ int K9F2G08_ReadPage(u32 block, u32 page, u8 *buffer, int len, u8 *ecc)
int i;
u32 _page = block*PAGES_PER_BLOCK + page;
// NF_RSTECC(); // Initialize ECC
/* NF_RSTECC(); */ /* Initialize ECC*/
nand_cs_en();
nand_write_cmd(K9F2G08_CMD_READ0); // Read command
nand_write_addr(0x00); // Column = 0
nand_write_cmd(NAND_CMD_READ0); /* Read command */
nand_write_addr(0x00); /* Column = 0 */
nand_write_addr(0x00);
nand_write_addr(_page&0xff); //
nand_write_addr((_page>>8)&0xff); // Block & Page num.
nand_write_addr((_page>>16)&0xff); //
nand_write_addr(_page&0xff);
nand_write_addr((_page>>8)&0xff);
nand_write_addr((_page>>16)&0xff);
nand_write_cmd(K9F2G08_CMD_READ30);
nand_write_cmd(NAND_CMD_READSTART);
nand_wait(); // Wait tR(max 12us)
nand_wait(); /* Wait tR(max 12us) */
for(i=0;i<len;i++)
{
buffer[i] = nand_read(); // Read one page
buffer[i] = nand_read(); /* Read one page */
}
nand_cs_ds();
......@@ -175,23 +174,23 @@ int K9F2G08_ReadTags(u32 block, u32 page, u8 *spare, int ofs, int len)
u32 _page = block*PAGES_PER_BLOCK + page;
// NF_RSTECC(); // Initialize ECC
/* NF_RSTECC(); */ /* Initialize ECC */
nand_cs_en();
nand_write_cmd(K9F2G08_CMD_READ0); // Read command
nand_write_addr((PAGE_DATA_SIZE+ofs)&0xff); // Column = 0
nand_write_cmd(NAND_CMD_READ0);
nand_write_addr((PAGE_DATA_SIZE+ofs)&0xff);
nand_write_addr(((PAGE_DATA_SIZE+ofs)>>8)&0xff);
nand_write_addr(_page&0xff); //
nand_write_addr((_page>>8)&0xff); // Block & Page num.
nand_write_addr((_page>>16)&0xff); //
nand_write_addr(_page&0xff);
nand_write_addr((_page>>8)&0xff);
nand_write_addr((_page>>16)&0xff);
nand_write_cmd(K9F2G08_CMD_READ30);
nand_write_cmd(NAND_CMD_READSTART);
nand_wait(); // Wait tR(max 12us)
nand_wait(); /* Wait tR(max 12us) */
for(i=0;i<len;i++)
{
spare[i] = nand_read(); // Read one page
spare[i] = nand_read(); /* Read one page */
}
nand_cs_ds();
......@@ -199,34 +198,36 @@ int K9F2G08_ReadTags(u32 block, u32 page, u8 *spare, int ofs, int len)
return 1;
}
//写一页数据
//返回0,successful
//返回1,error
/*
* write one page data
* return 0,successful
* return 1,error
*/
int K9F2G08_WritePage(u32 block, u32 page, const u8 *buffer, int len, const u8 *ecc)
{
int i,stat;
u32 _page = block*PAGES_PER_BLOCK + page;
//nand_Init_ECC(); // Initialize ECC
/* nand_Init_ECC(); */ /* nitialize ECC */
nand_cs_en();
nand_write_cmd(K9F2G08_CMD_SEQIN); //0x80 Write 1st command
nand_write_cmd(NAND_CMD_SEQIN);
for(i=0;i<10;i++);
nand_write_addr(0x00); // Column 0
nand_write_addr(0x00); /* Column 0 */
nand_write_addr(0x00);
nand_write_addr(_page&0xff); //
nand_write_addr((_page>>8)&0xff); // Block & page num.
nand_write_addr((_page>>16)&0xff); //
nand_write_addr(_page&0xff);
nand_write_addr((_page>>8)&0xff);
nand_write_addr((_page>>16)&0xff);
for(i=0;i<len;i++)
{
nand_write(*buffer++); // Write one page to NFM from buffer
nand_write(*buffer++);
}
nand_write_cmd(K9F2G08_CMD_PAGEPROG); //0x10 Write 2nd command
nand_write_cmd(NAND_CMD_PAGEPROG);
nand_wait(); //wait tPROG 200~500us;
nand_wait(); /* wait tPROG 200~500us; */
stat = read_nand_stats();
nand_cs_ds();
......@@ -239,29 +240,29 @@ int K9F2G08_WriteTags(u32 block, u32 page, const u8 *spare, int ofs, int len)
int i,stat;
u32 _page = block*PAGES_PER_BLOCK + page;
//nand_Init_ECC(); // Initialize ECC
/* nand_Init_ECC(); */ /* Initialize ECC */
nand_cs_en();
nand_write_cmd(K9F2G08_CMD_SEQIN); //0x80 Write 1st command
nand_write_cmd(NAND_CMD_SEQIN);
for(i=0;i<10;i++);
nand_write_addr((PAGE_DATA_SIZE+ofs)&0xff); // Column 0
nand_write_addr((PAGE_DATA_SIZE+ofs)&0xff);
nand_write_addr(((PAGE_DATA_SIZE+ofs)>>8)&0xff);
nand_write_addr(_page&0xff); //
nand_write_addr((_page>>8)&0xff); // Block & page num.
nand_write_addr((_page>>16)&0xff); //
nand_write_addr(_page&0xff);
nand_write_addr((_page>>8)&0xff);
nand_write_addr((_page>>16)&0xff);
for(i=0;i<len;i++)
{
nand_write(*spare++); // Write one page to NFM from buffer
nand_write(*spare++);
}
nand_write_cmd(K9F2G08_CMD_PAGEPROG); //0x10 Write 2nd command
nand_write_cmd(NAND_CMD_PAGEPROG);
nand_wait(); //wait tPROG 200~500us;
nand_wait(); /* wait tPROG 200~500us; */
stat = read_nand_stats();
if(!stat) // Page write error
if(!stat) /* Page write error */
{
nand_cs_ds();
return 0;
......@@ -273,38 +274,21 @@ int K9F2G08_WriteTags(u32 block, u32 page, const u8 *spare, int ofs, int len)
}
}
//find frist shift bit
//rt_inline int generic_ffs(int x)
//{
// int r = 1;
//
// if(!x)
// return 0;
//
// if(!(x & 0xffff)) {x >>= 16;r += 16;}
// if(!(x & 0xff)) {x >>= 8;r += 8;}
// if(!(x & 0xf)) {x >>= 4;r += 4;}
// if(!(x & 3)) {x >>= 2;r += 2;}
// if(!(x & 1)) {x >>= 1;r += 1;}
//
// return r;
//}
/* when all is true,read all byte */
void K9F2G08_ReadChipID(u8* buf, UBOOL all)
{
nand_cs_en();
nand_write_cmd(K9F2G08_CMD_READID); //0x90
nand_write_addr(K9F2G08_CMD_READ0);
nand_write_cmd(NAND_CMD_READID);
nand_write_addr(NAND_CMD_READ0);
buf[0] = nand_read();//制造商ID
buf[1] = nand_read();//芯片ID
buf[0] = nand_read();/* manufacturer ID */
buf[1] = nand_read();/* physical chip ID */
if(all)
{
buf[2] = nand_read();
buf[3] = nand_read();
//buf[4] = nand_read(); //有的芯片没有第5个字节
/* buf[4] = nand_read(); */ /* Some chips have no 5th byte */
}
nand_cs_ds();
......@@ -315,17 +299,17 @@ void K9F2G08_Init(void)
NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
NFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
NFSTAT = 0;
// 1 1 1 1, 1 xxx, r xxx, r xxx
// En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1
/* 1 1 1 1, 1 xxx, r xxx, r xxx */
/* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */
}
void K9F2G08_Reset(void)
{
nand_cs_en();
nand_write_cmd(0xFF); //reset command
nand_write_cmd(0xFF); /* reset command */
nand_wait(); //wait 200~500us;
nand_wait(); /* wait 200~500us */
nand_cs_ds();
K9F2G08_Init();
......@@ -338,24 +322,24 @@ int K9F2G08_ReadChunk(u32 chunk, u8 *data, u8 *tags)
nand_cs_en();
nand_write_cmd(K9F2G08_CMD_READ0); // Read command
nand_write_cmd(NAND_CMD_READ0);
nand_write_addr(0x00);
nand_write_addr(0x00);
nand_write_addr(chunk & 0xff); //
nand_write_addr((chunk >> 8) & 0xff); // Block & Page num.
nand_write_addr(chunk & 0xff);
nand_write_addr((chunk >> 8) & 0xff);
nand_write_addr((chunk >> 16) & 0xff); //
//nand_Init_ECC();
nand_write_cmd(K9F2G08_CMD_READ30); // Read command
/* nand_Init_ECC(); */
nand_write_cmd(NAND_CMD_READ30);
nand_wait(); // Wait tR(max 12us)
nand_wait(); /* Wait tR(max 12us) */
for(i = 0; i < PAGE_DATA_SIZE; i++)
{
data[i] = nand_read(); // Read one page
data[i] = nand_read(); /* Read page data */
}
for(i = 0; i < PAGE_SPARE_SIZE; i++)
{
tags[i] = nand_read(); // Read spare array
tags[i] = nand_read(); /* Read spare array */
}
nand_cs_ds();
......
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
--*/
#ifndef __NAND_H__
#define __NAND_H__
/*
* uffs/flash/nand.h
*
* COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Info:
* Contains standard defines and IDs for NAND flash devices
*/
#ifndef __RTT_DFS_NAND_H__
#define __RTT_DFS_NAND_H__
#include <s3c24x0.h>
#include <uffs/uffs_types.h>
/*
* Standard NAND flash commands
*/
#define NAND_CMD_READ0 0 /* Read0 */
#define NAND_CMD_READ1 1 /* Read1 */
#define NAND_CMD_RNDOUT 5 /* Random data output */
#define NAND_CMD_PAGEPROG 0x10 /* Write phase 2 */
#define NAND_CMD_READOOB 0x50 /* Read oob */
#define NAND_CMD_ERASE1 0x60 /* Erase phase 1 */
#define NAND_CMD_STATUS 0x70 /* Status read */
#define NAND_CMD_STATUS_MULTI 0x71
#define NAND_CMD_SEQIN 0x80 /* Write phase 1 */
#define NAND_CMD_RNDIN 0x85 /* Random data input */
#define NAND_CMD_READID 0x90 /* ReadID,all-purpose command */
#define NAND_CMD_ERASE2 0xd0 /* Erase phase 2 */
#define NAND_CMD_RESET 0xff /* Reset */
/* Extended commands for large page devices */
#define NAND_CMD_READSTART 0x30
#define NAND_CMD_RNDOUTSTART 0xE0
#define NAND_CMD_CACHEDPROG 0x15
#define NAND_CMD_READ_EDC 0x7b
/* define low accessing value */
#define TOTAL_BLOCKS 2048 /* total block of whole chip */
......@@ -28,9 +44,9 @@ PARTICULAR PURPOSE.
#define PAGE_SIZE (PAGE_DATA_SIZE+PAGE_SPARE_SIZE)/* max size per whole page */
#define BLOCK_DATA_SIZE (PAGE_DATA_SIZE*PAGES_PER_BLOCK)/* max size per block' */
//bad flags offset in the oob area.
#define NAND_SMALL_BADBLOCK_POS 5 //small page FLASH
#define NAND_LARGE_BADBLOCK_POS 0 //large page FLASH
/* bad flags offset in the oob area. */
#define NAND_SMALL_BADBLOCK_POS 5 /* small page FLASH */
#define NAND_LARGE_BADBLOCK_POS 0 /* large page FLASH */
/* Option constants for bizarre disfunctionality and real
* features
......@@ -56,16 +72,14 @@ PARTICULAR PURPOSE.
#define NAND_SAMSUNG_LP_OPTIONS \
(NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
struct nand_flash_dev
struct nand_flash_dev
{
char *name; //chip name
int id; //chip ID
unsigned long pagesize; //max pages
unsigned long chipsize; //size of whole chip iMB
unsigned long blocksize;//size of block
unsigned long options; //option
char *name; /* chip name */
int id; /* chip ID */
unsigned long pagesize; /* max pages */
unsigned long chipsize; /* size of whole chip iMB */
unsigned long blocksize;/* size of block */
unsigned long options; /* option */
};
struct nand_manufacturers
......@@ -74,4 +88,4 @@ struct nand_manufacturers
char * name;
};
#endif /*__NAND_H__*/
#endif /*__RTT_DFS_NAND_H__*/
......@@ -37,25 +37,25 @@
#ifndef _UFFS_H_
#define _UFFS_H_
#include <dfs_def.h>
#include <rtthread.h>
#include "uffs/uffs_types.h"
#ifdef __cplusplus
extern "C"{
#endif
#define UO_RDONLY DFS_O_RDONLY /** read only */
#define UO_WRONLY DFS_O_WRONLY /** write only */
#define UO_RDWR DFS_O_RDWR /** read and write */
#define UO_APPEND DFS_O_APPEND /** append */
#define UO_RDONLY 0x0000 /** read only */
#define UO_WRONLY 0x0001 /** write only */
#define UO_RDWR 0x0002 /** read and write */
#define UO_APPEND 0x0008 /** append */
#define UO_BINARY 0x0000 /** no used in uffs */
#define UO_CREATE DFS_O_CREAT
#define UO_TRUNC DFS_O_TRUNC
#define UO_EXCL DFS_O_EXCL
#define UO_DIR DFS_O_DIRECTORY /** open a directory */
#define UO_BINARY 0x0000 /** no used in uffs */
#define UO_CREATE 0x0100
#define UO_TRUNC 0x0200
#define UO_EXCL 0x0400
#define UO_DIR 0x1000 /** open a directory */
......@@ -85,9 +85,9 @@ extern "C"{
#define _SEEK_SET 1 /** seek from beginning of file */
#define _SEEK_END 2 /** seek from end of file */
#define USEEK_SET DFS_SEEK_SET /*0* 从当前点寻找 */
#define USEEK_CUR DFS_SEEK_CUR /*1* 从文件的开始寻找 */
#define USEEK_END DFS_SEEK_END /*2* 从文件的结尾寻找 */
#define USEEK_CUR _SEEK_CUR
#define USEEK_SET _SEEK_SET
#define USEEK_END _SEEK_END
......
/*
This file is part of UFFS, the Ultra-low-cost Flash File System.
Copyright (C) 2005-2009 Ricky Zheng <ricky_gz_zheng@yahoo.co.nz>
UFFS is free software; you can redistribute it and/or modify it under
the GNU Library General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
UFFS is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
or GNU Library General Public License, as applicable, for more details.
You should have received a copy of the GNU General Public License
and GNU Library General Public License along with UFFS; if not, write
to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
As a special exception, if other files instantiate templates or use
macros or inline functions from this file, or you compile this file
and link it with other works to produce a work based on this file,
this file does not by itself cause the resulting work to be covered
by the GNU General Public License. However the source code for this
file must still be made available in accordance with section (3) of
the GNU General Public License v2.
This exception does not invalidate any other reasons why a work based
on this file might be covered by the GNU General Public License.
*/
#include <string.h>
#include "uffs/uffs_config.h"
#include "uffs/uffs_device.h"
#include "uffs/uffs_mtb.h"
#include "uffs/uffs_utils.h"
#include "uffs/uffs_fs.h"
#include "uffs/uffs_fd.h"
#define PFX "fd: "
#define FD_OFFSET 3 //!< just make file handler more like POSIX (0, 1, 2 for stdin/stdout/stderr)
#define FD2OBJ(fd) (((fd) >= FD_OFFSET && (fd) < MAX_DIR_HANDLE + FD_OFFSET) ? \
(uffs_Object *)uffs_PoolGetBufByIndex(uffs_GetObjectPool(), (fd) - FD_OFFSET) : NULL )
#define OBJ2FD(obj) (uffs_PoolGetIndex(uffs_GetObjectPool(), obj) + FD_OFFSET)
#define CHK_OBJ(obj, ret) do { \
if (uffs_PoolVerify(uffs_GetObjectPool(), (obj)) == U_FALSE || \
uffs_PoolCheckFreeList(uffs_GetObjectPool(), (obj)) == U_TRUE) { \
uffs_set_error(-UEBADF); \
return (ret); \
} \
} while(0)
#define CHK_DIR(dirp, ret) do { \
if (uffs_PoolVerify(&_dir_pool, (dirp)) == U_FALSE || \
uffs_PoolCheckFreeList(&_dir_pool, (dirp)) == U_TRUE) { \
uffs_set_error(-UEBADF); \
return (ret); \
} \
} while(0)
#define CHK_DIR_VOID(dirp) do { \
if (uffs_PoolVerify(&_dir_pool, (dirp)) == U_FALSE || \
uffs_PoolCheckFreeList(&_dir_pool, (dirp)) == U_TRUE) { \
uffs_set_error(-UEBADF); \
return; \
} \
} while(0)
static int _dir_pool_data[sizeof(uffs_DIR) * MAX_DIR_HANDLE / sizeof(int)];
static uffs_Pool _dir_pool;
static int _uffs_errno = 0;
/**
* initialise uffs_DIR buffers, called by UFFS internal
*/
int uffs_InitDirEntryBuf(void)
{
return uffs_PoolInit(&_dir_pool, _dir_pool_data, sizeof(_dir_pool_data),
sizeof(uffs_DIR), MAX_DIR_HANDLE);
}
/**
* Release uffs_DIR buffers, called by UFFS internal
*/
int uffs_ReleaseDirEntryBuf(void)
{
return uffs_PoolRelease(&_dir_pool);
}
uffs_Pool * uffs_GetDirEntryBufPool(void)
{
return &_dir_pool;
}
static uffs_DIR * GetDirEntry(void)
{
uffs_DIR *dirp = (uffs_DIR *) uffs_PoolGet(&_dir_pool);
if(dirp)
memset(dirp, 0, sizeof(uffs_DIR));
return dirp;
}
static void PutDirEntry(uffs_DIR *p)
{
uffs_PoolPut(&_dir_pool, p);
}
/** get global errno
*/
int uffs_get_error(void)
{
return _uffs_errno;
}
/** set global errno
*/
int uffs_set_error(int err)
{
return (_uffs_errno = err);
}
/* POSIX compliant file system APIs */
int uffs_open(const char *name, int oflag, ...)
{
uffs_Object *obj;
int ret = 0;
obj = uffs_GetObject();
if (obj == NULL) {
uffs_set_error(-UEMFILE);
ret = -1;
}
else {
if (uffs_OpenObject(obj, name, oflag) == U_FAIL) {
uffs_set_error(-uffs_GetObjectErr(obj));
uffs_PutObject(obj);
ret = -1;
}
else {
ret = OBJ2FD(obj);
}
}
return ret;
}
int uffs_close(int fd)
{
int ret = 0;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
if (uffs_CloseObject(obj) == U_FAIL) {
uffs_set_error(-uffs_GetObjectErr(obj));
ret = -1;
}
else {
uffs_PutObject(obj);
ret = 0;
}
return ret;
}
int uffs_read(int fd, void *data, int len)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = uffs_ReadObject(obj, data, len);
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
int uffs_write(int fd, void *data, int len)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = uffs_WriteObject(obj, data, len);
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
long uffs_seek(int fd, long offset, int origin)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = uffs_SeekObject(obj, offset, origin);
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
long uffs_tell(int fd)
{
long ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = (long) uffs_GetCurOffset(obj);
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
int uffs_eof(int fd)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = uffs_EndOfFile(obj);
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
int uffs_flush(int fd)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = (uffs_FlushObject(obj) == U_SUCC) ? 0 : -1;
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
int uffs_rename(const char *old_name, const char *new_name)
{
int err = 0;
int ret = 0;
ret = (uffs_RenameObject(old_name, new_name, &err) == U_SUCC) ? 0 : -1;
uffs_set_error(-err);
return ret;
}
int uffs_remove(const char *name)
{
int err = 0;
int ret = 0;
struct uffs_stat st;
if (uffs_stat(name, &st) < 0) {
err = UENOENT;
ret = -1;
}
else if (st.st_mode & US_IFDIR) {
err = UEISDIR;
ret = -1;
}
else if (uffs_DeleteObject(name, &err) == U_SUCC) {
ret = 0;
}
else {
ret = -1;
}
uffs_set_error(-err);
return ret;
}
int uffs_truncate(int fd, long remain)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = (uffs_TruncateObject(obj, remain) == U_SUCC) ? 0 : -1;
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
static int do_stat(uffs_Object *obj, struct uffs_stat *buf)
{
uffs_ObjectInfo info;
int ret = 0;
int err = 0;
if (uffs_GetObjectInfo(obj, &info, &err) == U_FAIL) {
ret = -1;
}
else {
buf->st_dev = obj->dev->dev_num;
buf->st_ino = info.serial;
buf->st_nlink = 0;
buf->st_uid = 0;
buf->st_gid = 0;
buf->st_rdev = 0;
buf->st_size = info.len;
buf->st_blksize = obj->dev->com.pg_data_size;
buf->st_blocks = 0;
buf->st_atime = info.info.last_modify;
buf->st_mtime = info.info.last_modify;
buf->st_ctime = info.info.create_time;
buf->st_mode = (info.info.attr & FILE_ATTR_DIR ? US_IFDIR : US_IFREG);
if (info.info.attr & FILE_ATTR_WRITE)
buf->st_mode |= US_IRWXU;
}
uffs_set_error(-err);
return ret;
}
int uffs_stat(const char *name, struct uffs_stat *buf)
{
uffs_Object *obj;
int ret = 0;
int err = 0;
URET result;
obj = uffs_GetObject();
if (obj) {
if (*name && name[strlen(name) - 1] == '/') {
result = uffs_OpenObject(obj, name, UO_RDONLY | UO_DIR);
}
else {
if ((result = uffs_OpenObject(obj, name, UO_RDONLY)) != U_SUCC) // try file
result = uffs_OpenObject(obj, name, UO_RDONLY | UO_DIR); // then try dir
}
if (result == U_SUCC) {
ret = do_stat(obj, buf);
uffs_CloseObject(obj);
}
else {
err = uffs_GetObjectErr(obj);
ret = -1;
}
uffs_PutObject(obj);
}
else {
err = UENOMEM;
ret = -1;
}
uffs_set_error(-err);
return ret;
}
int uffs_lstat(const char *name, struct uffs_stat *buf)
{
return uffs_stat(name, buf);
}
int uffs_fstat(int fd, struct uffs_stat *buf)
{
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
return do_stat(obj, buf);
}
int uffs_closedir(uffs_DIR *dirp)
{
CHK_DIR(dirp, -1);
uffs_FindObjectClose(&dirp->f);
if (dirp->obj) {
uffs_CloseObject(dirp->obj);
uffs_PutObject(dirp->obj);
}
PutDirEntry(dirp);
return 0;
}
uffs_DIR * uffs_opendir(const char *path)
{
int err = 0;
uffs_DIR *ret = NULL;
uffs_DIR *dirp = GetDirEntry();
if (dirp) {
dirp->obj = uffs_GetObject();
if (dirp->obj) {
if (uffs_OpenObject(dirp->obj, path, UO_RDONLY | UO_DIR) == U_SUCC) {
if (uffs_FindObjectOpen(&dirp->f, dirp->obj) == U_SUCC) {
ret = dirp;
goto ext;
}
else {
uffs_CloseObject(dirp->obj);
}
}
else {
err = uffs_GetObjectErr(dirp->obj);
}
uffs_PutObject(dirp->obj);
dirp->obj = NULL;
}
else {
err = UEMFILE;
}
PutDirEntry(dirp);
}
else {
err = UEMFILE;
}
ext:
uffs_set_error(-err);
return ret;
}
struct uffs_dirent* uffs_readdir(uffs_DIR *dirp)
{
struct uffs_dirent *ent = &dirp->dirent;
//CHK_DIR(dirp, NULL);
if(dirp == NULL)
return NULL;
if(uffs_FindObjectNext(&dirp->info, &dirp->f) == RT_EOK)
{
ent->d_ino = dirp->info.serial;
ent->d_namelen = dirp->info.info.name_len;
memcpy(ent->d_name, dirp->info.info.name, ent->d_namelen);
ent->d_name[ent->d_namelen] = 0;
ent->d_off = dirp->f.pos;
ent->d_reclen = sizeof(struct uffs_dirent);
ent->d_type = dirp->info.info.attr;
return ent;
}
else
return NULL;
}
void uffs_rewinddir(uffs_DIR *dirp)
{
CHK_DIR_VOID(dirp);
uffs_FindObjectRewind(&dirp->f); //fi(=)find info
}
/*
* 函数功能: 创建一个文件夹
* 输入参数: 文件夹名称,参数
* 返回参数:
*/
int uffs_mkdir(const char *name, ...)
{
uffs_Object *obj;
int ret = 0;
int err = 0;
obj = uffs_GetObject();
if (obj) {
if (uffs_CreateObject(obj, name, UO_CREATE|UO_DIR) != U_SUCC) {
err = obj->err;
ret = -1;
}
else {
uffs_CloseObject(obj);
ret = 0;
}
uffs_PutObject(obj);
}
else {
err = UEMFILE;
ret = -1;
}
uffs_set_error(-err);
return ret;
}
/*
* 函数功能: 移除一个文件夹
* 输入参数: 文件夹名称
* 返回参数:
*/
int uffs_rmdir(const char *name)
{
int err = 0;
int ret = 0;
struct uffs_stat st;
if (uffs_stat(name, &st) < 0) {
err = UENOENT;
ret = -1;
}
else if ((st.st_mode & US_IFDIR) == 0) {
err = UENOTDIR;
ret = -1;
}
else if (uffs_DeleteObject(name, &err) == U_SUCC) {
ret = 0;
}
else {
ret = -1;
}
uffs_set_error(-err);
return ret;
}
/*
This file is part of UFFS, the Ultra-low-cost Flash File System.
Copyright (C) 2005-2009 Ricky Zheng <ricky_gz_zheng@yahoo.co.nz>
UFFS is free software; you can redistribute it and/or modify it under
the GNU Library General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
UFFS is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
or GNU Library General Public License, as applicable, for more details.
You should have received a copy of the GNU General Public License
and GNU Library General Public License along with UFFS; if not, write
to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
As a special exception, if other files instantiate templates or use
macros or inline functions from this file, or you compile this file
and link it with other works to produce a work based on this file,
this file does not by itself cause the resulting work to be covered
by the GNU General Public License. However the source code for this
file must still be made available in accordance with section (3) of
the GNU General Public License v2.
This exception does not invalidate any other reasons why a work based
on this file might be covered by the GNU General Public License.
*/
/**
* \file uffs_fd.c
* \brief POSIX like, hight level file operations
* \author Ricky Zheng, created 8th Jun, 2005
*/
#include <string.h>
#include "uffs/uffs_config.h"
#include "uffs/uffs_fs.h"
#include "uffs/uffs_fd.h"
#define PFX "fd: "
#define FD_OFFSET 3 //!< just make file handler more like POSIX (0, 1, 2 for stdin/stdout/stderr)
#define FD2OBJ(fd) (((fd) >= FD_OFFSET && (fd) < MAX_DIR_HANDLE + FD_OFFSET) ? \
(uffs_Object *)uffs_PoolGetBufByIndex(uffs_GetObjectPool(), (fd) - FD_OFFSET) : NULL )
#define OBJ2FD(obj) (uffs_PoolGetIndex(uffs_GetObjectPool(), obj) + FD_OFFSET)
#define CHK_OBJ(obj, ret) do { \
if (uffs_PoolVerify(uffs_GetObjectPool(), (obj)) == U_FALSE || \
uffs_PoolCheckFreeList(uffs_GetObjectPool(), (obj)) == U_TRUE) { \
uffs_set_error(-UEBADF); \
return (ret); \
} \
} while(0)
#define CHK_DIR(dirp, ret) do { \
if (uffs_PoolVerify(&_dir_pool, (dirp)) == U_FALSE || \
uffs_PoolCheckFreeList(&_dir_pool, (dirp)) == U_TRUE) { \
uffs_set_error(-UEBADF); \
return (ret); \
} \
} while(0)
#define CHK_DIR_VOID(dirp) do { \
if (uffs_PoolVerify(&_dir_pool, (dirp)) == U_FALSE || \
uffs_PoolCheckFreeList(&_dir_pool, (dirp)) == U_TRUE) { \
uffs_set_error(-UEBADF); \
return; \
} \
} while(0)
static int _dir_pool_data[sizeof(uffs_DIR) * MAX_DIR_HANDLE / sizeof(int)];
static uffs_Pool _dir_pool;
static int _uffs_errno = 0;
/**
* initialise uffs_DIR buffers, called by UFFS internal
*/
URET uffs_InitDirEntryBuf(void)
{
return uffs_PoolInit(&_dir_pool, _dir_pool_data, sizeof(_dir_pool_data),
sizeof(uffs_DIR), MAX_DIR_HANDLE);
}
/**
* Release uffs_DIR buffers, called by UFFS internal
*/
URET uffs_ReleaseDirEntryBuf(void)
{
return uffs_PoolRelease(&_dir_pool);
}
uffs_Pool * uffs_GetDirEntryBufPool(void)
{
return &_dir_pool;
}
static uffs_DIR * GetDirEntry(void)
{
uffs_DIR *dirp = (uffs_DIR *) uffs_PoolGet(&_dir_pool);
if (dirp)
memset(dirp, 0, sizeof(uffs_DIR));
return dirp;
}
static void PutDirEntry(uffs_DIR *p)
{
uffs_PoolPut(&_dir_pool, p);
}
/** get global errno
*/
int uffs_get_error(void)
{
return _uffs_errno;
}
/** set global errno
*/
int uffs_set_error(int err)
{
return (_uffs_errno = err);
}
/* POSIX compliant file system APIs */
int uffs_open(const char *name, int oflag, ...)
{
uffs_Object *obj;
int ret = 0;
obj = uffs_GetObject();
if (obj == NULL) {
uffs_set_error(-UEMFILE);
ret = -1;
}
else {
if (uffs_OpenObject(obj, name, oflag) == U_FAIL) {
uffs_set_error(-uffs_GetObjectErr(obj));
uffs_PutObject(obj);
ret = -1;
}
else {
ret = OBJ2FD(obj);
}
}
return ret;
}
int uffs_close(int fd)
{
int ret = 0;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
if (uffs_CloseObject(obj) == U_FAIL) {
uffs_set_error(-uffs_GetObjectErr(obj));
ret = -1;
}
else {
uffs_PutObject(obj);
ret = 0;
}
return ret;
}
int uffs_read(int fd, void *data, int len)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = uffs_ReadObject(obj, data, len);
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
int uffs_write(int fd, void *data, int len)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = uffs_WriteObject(obj, data, len);
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
long uffs_seek(int fd, long offset, int origin)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = uffs_SeekObject(obj, offset, origin);
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
long uffs_tell(int fd)
{
long ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = (long) uffs_GetCurOffset(obj);
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
int uffs_eof(int fd)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = uffs_EndOfFile(obj);
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
int uffs_flush(int fd)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = (uffs_FlushObject(obj) == U_SUCC) ? 0 : -1;
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
int uffs_rename(const char *old_name, const char *new_name)
{
int err = 0;
int ret = 0;
ret = (uffs_RenameObject(old_name, new_name, &err) == U_SUCC) ? 0 : -1;
uffs_set_error(-err);
return ret;
}
int uffs_remove(const char *name)
{
int err = 0;
int ret = 0;
struct uffs_stat st;
if (uffs_stat(name, &st) < 0) {
err = UENOENT;
ret = -1;
}
else if (st.st_mode & US_IFDIR) {
err = UEISDIR;
ret = -1;
}
else if (uffs_DeleteObject(name, &err) == U_SUCC) {
ret = 0;
}
else {
ret = -1;
}
uffs_set_error(-err);
return ret;
}
int uffs_truncate(int fd, long remain)
{
int ret;
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
uffs_ClearObjectErr(obj);
ret = (uffs_TruncateObject(obj, remain) == U_SUCC) ? 0 : -1;
uffs_set_error(-uffs_GetObjectErr(obj));
return ret;
}
static int do_stat(uffs_Object *obj, struct uffs_stat *buf)
{
uffs_ObjectInfo info;
int ret = 0;
int err = 0;
if (uffs_GetObjectInfo(obj, &info, &err) == U_FAIL) {
ret = -1;
}
else {
buf->st_dev = obj->dev->dev_num;
buf->st_ino = info.serial;
buf->st_nlink = 0;
buf->st_uid = 0;
buf->st_gid = 0;
buf->st_rdev = 0;
buf->st_size = info.len;
buf->st_blksize = obj->dev->com.pg_data_size;
buf->st_blocks = 0;
buf->st_atime = info.info.last_modify;
buf->st_mtime = info.info.last_modify;
buf->st_ctime = info.info.create_time;
buf->st_mode = (info.info.attr & FILE_ATTR_DIR ? US_IFDIR : US_IFREG);
if (info.info.attr & FILE_ATTR_WRITE)
buf->st_mode |= US_IRWXU;
}
uffs_set_error(-err);
return ret;
}
int uffs_stat(const char *name, struct uffs_stat *buf)
{
uffs_Object *obj;
int ret = 0;
int err = 0;
URET result;
obj = uffs_GetObject();
if (obj) {
if (*name && name[strlen(name) - 1] == '/') {
result = uffs_OpenObject(obj, name, UO_RDONLY | UO_DIR);
}
else {
if ((result = uffs_OpenObject(obj, name, UO_RDONLY)) != U_SUCC) // try file
result = uffs_OpenObject(obj, name, UO_RDONLY | UO_DIR); // then try dir
}
if (result == U_SUCC) {
ret = do_stat(obj, buf);
uffs_CloseObject(obj);
}
else {
err = uffs_GetObjectErr(obj);
ret = -1;
}
uffs_PutObject(obj);
}
else {
err = UENOMEM;
ret = -1;
}
uffs_set_error(-err);
return ret;
}
int uffs_lstat(const char *name, struct uffs_stat *buf)
{
return uffs_stat(name, buf);
}
int uffs_fstat(int fd, struct uffs_stat *buf)
{
uffs_Object *obj = FD2OBJ(fd);
CHK_OBJ(obj, -1);
return do_stat(obj, buf);
}
int uffs_closedir(uffs_DIR *dirp)
{
CHK_DIR(dirp, -1);
uffs_FindObjectClose(&dirp->f);
if (dirp->obj) {
uffs_CloseObject(dirp->obj);
uffs_PutObject(dirp->obj);
}
PutDirEntry(dirp);
return 0;
}
uffs_DIR * uffs_opendir(const char *path)
{
int err = 0;
uffs_DIR *ret = NULL;
uffs_DIR *dirp = GetDirEntry();
if (dirp) {
dirp->obj = uffs_GetObject();
if (dirp->obj) {
if (uffs_OpenObject(dirp->obj, path, UO_RDONLY | UO_DIR) == U_SUCC) {
if (uffs_FindObjectOpen(&dirp->f, dirp->obj) == U_SUCC) {
ret = dirp;
goto ext;
}
else {
uffs_CloseObject(dirp->obj);
}
}
else {
err = uffs_GetObjectErr(dirp->obj);
}
uffs_PutObject(dirp->obj);
dirp->obj = NULL;
}
else {
err = UEMFILE;
}
PutDirEntry(dirp);
}
else {
err = UEMFILE;
}
ext:
uffs_set_error(-err);
return ret;
}
struct uffs_dirent * uffs_readdir(uffs_DIR *dirp)
{
struct uffs_dirent *ent;
CHK_DIR(dirp, NULL);
if (uffs_FindObjectNext(&dirp->info, &dirp->f) == U_SUCC) {
ent = &dirp->dirent;
ent->d_ino = dirp->info.serial;
ent->d_namelen = dirp->info.info.name_len;
memcpy(ent->d_name, dirp->info.info.name, ent->d_namelen);
ent->d_name[ent->d_namelen] = 0;
ent->d_off = dirp->f.pos;
ent->d_reclen = sizeof(struct uffs_dirent);
ent->d_type = dirp->info.info.attr;
return ent;
}
else
return NULL;
}
void uffs_rewinddir(uffs_DIR *dirp)
{
CHK_DIR_VOID(dirp);
uffs_FindObjectRewind(&dirp->f);
}
int uffs_mkdir(const char *name, ...)
{
uffs_Object *obj;
int ret = 0;
int err = 0;
obj = uffs_GetObject();
if (obj) {
if (uffs_CreateObject(obj, name, UO_CREATE|UO_DIR) != U_SUCC) {
err = obj->err;
ret = -1;
}
else {
uffs_CloseObject(obj);
ret = 0;
}
uffs_PutObject(obj);
}
else {
err = UEMFILE;
ret = -1;
}
uffs_set_error(-err);
return ret;
}
int uffs_rmdir(const char *name)
{
int err = 0;
int ret = 0;
struct uffs_stat st;
if (uffs_stat(name, &st) < 0) {
err = UENOENT;
ret = -1;
}
else if ((st.st_mode & US_IFDIR) == 0) {
err = UENOTDIR;
ret = -1;
}
else if (uffs_DeleteObject(name, &err) == U_SUCC) {
ret = 0;
}
else {
ret = -1;
}
uffs_set_error(-err);
return ret;
}
#if 0
void uffs_seekdir(uffs_DIR *dirp, long loc)
{
return ;
}
long uffs_telldir(uffs_DIR *dirp)
{
return 0;
}
#endif
......@@ -19,7 +19,7 @@
#include "uffs_ext.h"
#include <dfs_posix.h>
#include <filerw.h>
#include <rtgui/filerw.h>
#ifdef RT_USING_FINSH
#include <finsh.h>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册