/** * \brief initialize tree buffers * \param[in] dev uffs device */ URET uffs_TreeInit(uffs_Device *dev) { int size; int num; uffs_Pool *pool; int i; size = sizeof(TreeNode); num = dev->par.end - dev->par.start + 1; pool = &(dev->mem.tree_pool); if (dev->mem.tree_nodes_pool_size == 0) { if (dev->mem.malloc) { dev->mem.tree_nodes_pool_buf = dev->mem.malloc(dev, size * num); if (dev->mem.tree_nodes_pool_buf) dev->mem.tree_nodes_pool_size = size * num; } } if (size * num > dev->mem.tree_nodes_pool_size) { uffs_Perror(UFFS_MSG_DEAD, "Tree buffer require %d but only %d available.", size * num, dev->mem.tree_nodes_pool_size); memset(pool, 0, sizeof(uffs_Pool)); return U_FAIL; } uffs_Perror(UFFS_MSG_NOISY, "alloc tree nodes %d bytes.", size * num); uffs_PoolInit(pool, dev->mem.tree_nodes_pool_buf, dev->mem.tree_nodes_pool_size, size, num, U_FALSE); dev->tree.erased = NULL; dev->tree.erased_tail = NULL; dev->tree.erased_count = 0; dev->tree.bad = NULL; dev->tree.bad_count = 0; for (i = 0; i < DIR_NODE_ENTRY_LEN; i++) { dev->tree.dir_entry[i] = EMPTY_NODE; } for (i = 0; i < FILE_NODE_ENTRY_LEN; i++) { dev->tree.file_entry[i] = EMPTY_NODE; } for (i = 0; i < DATA_NODE_ENTRY_LEN; i++) { dev->tree.data_entry[i] = EMPTY_NODE; } dev->tree.max_serial = ROOT_DIR_SERIAL; return U_SUCC; }
/** * 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); }
/** * initialise object buffers, called by UFFS internal */ URET uffs_InitObjectBuf(void) { return uffs_PoolInit(&_object_pool, _object_data, sizeof(_object_data), sizeof(uffs_Object), MAX_OBJECT_HANDLE, U_FALSE); }
/** * Initialize UFFS flash interface */ URET uffs_FlashInterfaceInit(uffs_Device *dev) { URET ret = U_FAIL; struct uffs_StorageAttrSt *attr = dev->attr; uffs_Pool *pool = SPOOL(dev); if (dev->mem.spare_pool_size == 0) { if (dev->mem.malloc) { dev->mem.spare_pool_buf = dev->mem.malloc(dev, UFFS_SPARE_BUFFER_SIZE); if (dev->mem.spare_pool_buf) dev->mem.spare_pool_size = UFFS_SPARE_BUFFER_SIZE; } } if (UFFS_SPARE_BUFFER_SIZE > dev->mem.spare_pool_size) { uffs_Perror(UFFS_MSG_DEAD, "Spare buffer require %d but only %d available.", UFFS_SPARE_BUFFER_SIZE, dev->mem.spare_pool_size); memset(pool, 0, sizeof(uffs_Pool)); goto ext; } uffs_Perror(UFFS_MSG_NOISY, "alloc spare buffers %d bytes.", UFFS_SPARE_BUFFER_SIZE); uffs_PoolInit(pool, dev->mem.spare_pool_buf, dev->mem.spare_pool_size, UFFS_MAX_SPARE_SIZE, MAX_SPARE_BUFFERS); // init flash driver if (dev->ops->InitFlash) { if (dev->ops->InitFlash(dev) < 0) goto ext; } if (dev->ops->WritePage == NULL && dev->ops->WritePageWithLayout == NULL) { uffs_Perror(UFFS_MSG_SERIOUS, "Flash driver must provide 'WritePage' or 'WritePageWithLayout' function!"); goto ext; } if (dev->ops->ReadPage == NULL && dev->ops->ReadPageWithLayout == NULL) { uffs_Perror(UFFS_MSG_SERIOUS, "Flash driver must provide 'ReadPage' or 'ReadPageWithLayout' function!"); goto ext; } if (dev->attr->layout_opt == UFFS_LAYOUT_UFFS) { /* sanity check */ if (dev->attr->ecc_size == 0 && dev->attr->ecc_opt != UFFS_ECC_NONE) { dev->attr->ecc_size = NOMINAL_ECC_SIZE(dev); } uffs_Perror(UFFS_MSG_NORMAL, "ECC size %d", dev->attr->ecc_size); if ((dev->attr->data_layout && !dev->attr->ecc_layout) || (!dev->attr->data_layout && dev->attr->ecc_layout)) { uffs_Perror(UFFS_MSG_SERIOUS, "Please setup data_layout and ecc_layout, " "or leave them all NULL !"); goto ext; } if (!attr->data_layout && !attr->ecc_layout) { #if defined(CONFIG_UFFS_AUTO_LAYOUT_USE_MTD_SCHEME) switch(attr->page_data_size) { case 512: attr->ecc_layout = MTD512_LAYOUT_ECC; attr->data_layout = MTD512_LAYOUT_DATA; break; case 2048: attr->ecc_layout = MTD2K_LAYOUT_ECC; attr->data_layout = MTD2K_LAYOUT_DATA; break; default: InitSpareLayout(dev); break; } #else InitSpareLayout(dev); #endif } } else if (dev->attr->layout_opt == UFFS_LAYOUT_FLASH) { if (dev->ops->WritePageWithLayout == NULL || dev->ops->ReadPageWithLayout == NULL) { uffs_Perror(UFFS_MSG_SERIOUS, "When using UFFS_LAYOUT_FLASH option, " "flash driver must provide 'WritePageWithLayout' and 'ReadPageWithLayout' function!"); goto ext; } } else { uffs_Perror(UFFS_MSG_SERIOUS, "Invalid layout_opt: %d", dev->attr->layout_opt); goto ext; } if (dev->ops->EraseBlock == NULL) { uffs_Perror(UFFS_MSG_SERIOUS, "Flash driver MUST implement 'EraseBlock()' function !"); goto ext; } dev->mem.spare_data_size = CalculateSpareDataSize(dev); uffs_Perror(UFFS_MSG_NORMAL, "UFFS consume spare data size %d", dev->mem.spare_data_size); if (dev->mem.spare_data_size > dev->attr->spare_size) { uffs_Perror(UFFS_MSG_SERIOUS, "NAND spare(%dB) can't hold UFFS spare data(%dB) !", dev->attr->spare_size, dev->mem.spare_data_size); goto ext; } ret = U_SUCC; ext: return ret; }