static int nand_read_page( uffs_Device *dev, u32 block, u32 page, u8 *data, int data_len, u8 * ecc, rt_uint8_t *spare, int spare_len) { int res; page = block * dev->attr->pages_per_block + page; if (data == NULL && spare == NULL) { #if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) RT_ASSERT(0); //should not be here #else /* check block status: bad or good */ rt_uint8_t spare[UFFS_MAX_SPARE_SIZE]; rt_memset(spare, 0, UFFS_MAX_SPARE_SIZE); rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private), page, RT_NULL, 0, spare, dev->attr->spare_size);//dev->mem.spare_data_size res = spare[dev->attr->block_status_offs] == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK; return res; #endif } rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private), page, data, data_len, spare, spare_len); return UFFS_FLASH_NO_ERR; }
static int nand_mark_badblock(uffs_Device *dev, unsigned block) { int res; res = rt_mtd_nand_mark_badblock(RT_MTD_NAND_DEVICE(dev->_private), block); return res == RT_EOK ? UFFS_FLASH_NO_ERR : UFFS_FLASH_IO_ERR; }
static int nand_write_page(uffs_Device *dev, u32 block, u32 page, const u8 *data, int data_len, const u8 *spare, int spare_len) { int res; RT_ASSERT(UFFS_MAX_SPARE_SIZE >= dev->attr->spare_size); page = block * dev->attr->pages_per_block + page; if (data == NULL && spare == NULL) { #if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) RT_ASSERT(0); //should not be here #else /* mark bad block */ rt_uint8_t spare[UFFS_MAX_SPARE_SIZE]; rt_memset(spare, 0xFF, UFFS_MAX_SPARE_SIZE); spare[dev->attr->block_status_offs] = 0x00; res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private), page, RT_NULL, 0, spare, dev->attr->spare_size);//dev->mem.spare_data_size if (res != RT_EOK) goto __error; #endif } res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private), page, data, data_len, spare, spare_len); if (res != RT_EOK) goto __error; return UFFS_FLASH_NO_ERR; __error: return UFFS_FLASH_IO_ERR; }
static int dfs_uffs_mount( struct dfs_filesystem* fs, unsigned long rwflag, const void* data) { rt_base_t index; uffs_MountTable * mount_part; struct rt_mtd_nand_device * dev; RT_ASSERT(rt_strlen(fs->path) < (UFFS_MOUNT_PATH_MAX-1)); dev = RT_MTD_NAND_DEVICE(fs->dev_id); /*1. find a empty entry in partition table */ for (index = 0; index < UFFS_DEVICE_MAX ; index ++) { if (nand_part[index].dev == RT_NULL) break; } if (index == UFFS_DEVICE_MAX) return -DFS_STATUS_ENOENT; /*2. fill partition structure */ nand_part[index].dev = dev; /* make a right mount path for uffs, end with '/' */ rt_snprintf(nand_part[index].mount_path, UFFS_MOUNT_PATH_MAX, "%s/", fs->path); if (nand_part[index].mount_path[1] == '/') nand_part[index].mount_path[1] = 0; mount_part = &(nand_part[index].mount_table); mount_part->mount = nand_part[index].mount_path; mount_part->dev = &(nand_part[index].uffs_dev); rt_memset(mount_part->dev, 0, sizeof(uffs_Device));//in order to make uffs happy. mount_part->dev->_private = dev; /* save dev_id into uffs */ mount_part->start_block = dev->block_start; mount_part->end_block = dev->block_end; /*3. mount uffs */ if (init_uffs_fs(&nand_part[index]) < 0) { return uffs_result_to_dfs(uffs_get_error()); } return 0; }
static int dfs_uffs_unmount(struct dfs_filesystem* fs) { rt_base_t index; int result; /* find the device index and then unmount it */ for (index = 0; index < UFFS_DEVICE_MAX; index++) { if (nand_part[index].dev == RT_MTD_NAND_DEVICE(fs->dev_id)) { nand_part[index].dev = RT_NULL; result = uffs_UnMount(nand_part[index].mount_path); if (result != U_SUCC) break; result = uffs_UnRegisterMountTable(& nand_part[index].mount_table); return (result == U_SUCC) ? DFS_STATUS_OK : -1; } } return -DFS_STATUS_ENOENT; }
static int dfs_uffs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st) { int result; struct uffs_stat s; struct rt_mtd_nand_device * mtd; result = uffs_stat(path, &s); if (result < 0) return uffs_result_to_dfs(uffs_get_error()); /* convert uffs stat to dfs stat structure */ /* FIXME, these field may not be the same */ st->st_dev = 0; st->st_mode = s.st_mode; st->st_size = s.st_size; st->st_mtime = s.st_mtime; mtd = RT_MTD_NAND_DEVICE(fs->dev_id); st->st_blksize = mtd->page_size; return 0; }
static int dfs_uffs_statfs(struct dfs_filesystem* fs, struct statfs *buf) { rt_base_t index; struct rt_mtd_nand_device * mtd = RT_MTD_NAND_DEVICE(fs->dev_id); RT_ASSERT(mtd != RT_NULL); /* find the device index */ for (index = 0; index < UFFS_DEVICE_MAX; index++) { if (nand_part[index].dev == (void *)mtd) break; } if (index == UFFS_DEVICE_MAX) return -ENOENT; buf->f_bsize = mtd->page_size*mtd->pages_per_block; buf->f_blocks = (mtd->block_end - mtd->block_start + 1); buf->f_bfree = uffs_GetDeviceFree(&nand_part[index].uffs_dev)/buf->f_bsize ; return 0; }
static URET ReadPageWithLayout(uffs_Device *dev, u32 block, u32 page, u8 *data, int data_len, u8 *ecc, //NULL uffs_TagStore *ts, u8 *ecc_store) //NULL { int res = UFFS_FLASH_NO_ERR; int spare_len; rt_uint8_t spare[UFFS_MAX_SPARE_SIZE]; RT_ASSERT(UFFS_MAX_SPARE_SIZE >= dev->attr->spare_size); page = block * dev->attr->pages_per_block + page; spare_len = dev->mem.spare_data_size; if (data == RT_NULL && ts == RT_NULL) { #if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) RT_ASSERT(0); //should not be here #else /* check block good or bad */ rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private), page, RT_NULL, 0, spare, dev->attr->spare_size);//dev->mem.spare_data_size dev->st.io_read++; res = spare[dev->attr->block_status_offs] == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK; return res; #endif } if (data != RT_NULL) { dev->st.io_read += data_len; dev->st.page_read_count++; } res = rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private), page, data, data_len, spare, spare_len); if (res == 0) res = UFFS_FLASH_NO_ERR; else if (res == -1) { //TODO ecc correct, add code to use hardware do ecc correct res = UFFS_FLASH_ECC_OK; } else res = UFFS_FLASH_ECC_FAIL; if (ts != RT_NULL) { // unload ts and ecc from spare, you can modify it if you like uffs_FlashUnloadSpare(dev, (const u8 *)spare, ts, RT_NULL); if ((spare[spare_len - 1] == 0xFF) && (res == UFFS_FLASH_NO_ERR)) res = UFFS_FLASH_NOT_SEALED; dev->st.io_read += spare_len; dev->st.spare_read_count++; } return res; }
static int WritePageWithLayout(uffs_Device *dev, u32 block, u32 page, const u8 *data, int data_len, const u8 *ecc, //NULL const uffs_TagStore *ts) { int res; int spare_len; rt_uint8_t spare[UFFS_MAX_SPARE_SIZE]; RT_ASSERT(UFFS_MAX_SPARE_SIZE >= dev->attr->spare_size); page = block * dev->attr->pages_per_block + page; spare_len = dev->mem.spare_data_size; if (data == NULL && ts == NULL) { #if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) RT_ASSERT(0); //should not be here #else /* mark bad block */ rt_memset(spare, 0xFF, UFFS_MAX_SPARE_SIZE); spare[dev->attr->block_status_offs] = 0x00; res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private), page, RT_NULL, 0, spare, dev->attr->spare_size);//dev->mem.spare_data_size if (res != RT_EOK) goto __error; dev->st.io_write++; return UFFS_FLASH_NO_ERR; #endif } if (data != NULL && data_len != 0) { RT_ASSERT(data_len == dev->attr->page_data_size); dev->st.page_write_count++; dev->st.io_write += data_len; } if (ts != RT_NULL) { uffs_FlashMakeSpare(dev, ts, RT_NULL, (u8 *)spare); dev->st.spare_write_count++; dev->st.io_write += spare_len; } res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private), page, data, data_len, spare, spare_len); if (res != RT_EOK) goto __error; return UFFS_FLASH_NO_ERR; __error: return UFFS_FLASH_IO_ERR; }