From 8d77fe70dc8a93576933402d609e09a9768ec552 Mon Sep 17 00:00:00 2001 From: "iamyhw@gmail.com" Date: Sun, 3 Apr 2011 10:13:21 +0000 Subject: [PATCH] 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 --- components/dfs/filesystems/uffs/dfs_nand_if.c | 63 +- components/dfs/filesystems/uffs/dfs_uffs.c | 99 +- .../dfs/filesystems/uffs/flash/K9F2G08.h | 1 + .../dfs/filesystems/uffs/flash/k9f2g08.c | 272 ++--- components/dfs/filesystems/uffs/flash/nand.h | 80 +- .../dfs/filesystems/uffs/src/inc/uffs/uffs.h | 30 +- .../dfs/filesystems/uffs/src/uffs/uffs_fd.c | 1063 +++++++++-------- components/dfs/filesystems/uffs/uffs_ext.c | 2 +- 8 files changed, 816 insertions(+), 794 deletions(-) diff --git a/components/dfs/filesystems/uffs/dfs_nand_if.c b/components/dfs/filesystems/uffs/dfs_nand_if.c index 0e57c9c55..e56080cb6 100644 --- a/components/dfs/filesystems/uffs/dfs_nand_if.c +++ b/components/dfs/filesystems/uffs/dfs_nand_if.c @@ -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 @@ -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 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 */ diff --git a/components/dfs/filesystems/uffs/dfs_uffs.c b/components/dfs/filesystems/uffs/dfs_uffs.c index 9772b61b1..dea5eef01 100644 --- a/components/dfs/filesystems/uffs/dfs_uffs.c +++ b/components/dfs/filesystems/uffs/dfs_uffs.c @@ -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; diff --git a/components/dfs/filesystems/uffs/flash/K9F2G08.h b/components/dfs/filesystems/uffs/flash/K9F2G08.h index 3d6397cde..b7d28bec7 100644 --- a/components/dfs/filesystems/uffs/flash/K9F2G08.h +++ b/components/dfs/filesystems/uffs/flash/K9F2G08.h @@ -2,6 +2,7 @@ #define __K9F2G08_H__ #include +#include #include void K9F2G08_Program(u32 blockIndex, u32 srcAddress, u32 fileSize); diff --git a/components/dfs/filesystems/uffs/flash/k9f2g08.c b/components/dfs/filesystems/uffs/flash/k9f2g08.c index 332ddf408..37ca52631 100644 --- a/components/dfs/filesystems/uffs/flash/k9f2g08.c +++ b/components/dfs/filesystems/uffs/flash/k9f2g08.c @@ -1,10 +1,21 @@ -/** - * 用户要自己实现这个文件中的接口函数,不一样的芯片会有不同的访问命令 - * 这个例程文件是关于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 + #include #include "s3c24x0.h" - #include #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>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>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>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>= 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(); diff --git a/components/dfs/filesystems/uffs/flash/nand.h b/components/dfs/filesystems/uffs/flash/nand.h index 9ea725191..78075a329 100644 --- a/components/dfs/filesystems/uffs/flash/nand.h +++ b/components/dfs/filesystems/uffs/flash/nand.h @@ -1,24 +1,40 @@ -// -// 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 -#include +/* + * 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__*/ diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs.h index 9a1f8f37f..a0ee04075 100644 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs.h +++ b/components/dfs/filesystems/uffs/src/inc/uffs/uffs.h @@ -37,25 +37,25 @@ #ifndef _UFFS_H_ #define _UFFS_H_ -#include +#include #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 diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_fd.c b/components/dfs/filesystems/uffs/src/uffs/uffs_fd.c index 7d6261873..cad91346f 100644 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_fd.c +++ b/components/dfs/filesystems/uffs/src/uffs/uffs_fd.c @@ -1,531 +1,532 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - 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 -#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 + + 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 +#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 diff --git a/components/dfs/filesystems/uffs/uffs_ext.c b/components/dfs/filesystems/uffs/uffs_ext.c index 8c5a6578e..1465e942c 100644 --- a/components/dfs/filesystems/uffs/uffs_ext.c +++ b/components/dfs/filesystems/uffs/uffs_ext.c @@ -19,7 +19,7 @@ #include "uffs_ext.h" #include -#include +#include #ifdef RT_USING_FINSH #include -- GitLab