static bool node_hash_add(fatfs_hash_table_t *tbl, fatfs_node_t *node) { unsigned int hval; // Calculate hash of given node filename hval = hash_fn(node->dentry.filename, strlen(node->dentry.filename)) % tbl->size; CYG_TRACE2(TNC, "name='%s' hval=%d", node->dentry.filename, hval); if (tbl->nodes[hval] == NULL) { // First node in this slot node->hash_next = NULL; tbl->nodes[hval] = node; tbl->n++; return true; } else { // More nodes in this slot fatfs_node_t *lnode, *pnode; pnode = NULL; lnode = tbl->nodes[hval]; // Insert node into list so that it is sorted by filename while (lnode != NULL) { if (lnode == node) return false; if (strcasecmp(lnode->dentry.filename, node->dentry.filename) > 0) { if (pnode != NULL) pnode->hash_next = node; // Insert in the middle else tbl->nodes[hval] = node; // Insert at the beginning node->hash_next = lnode; tbl->n++; return true; } pnode = lnode; lnode = lnode->hash_next; } // Insert at the end pnode->hash_next = node; node->hash_next = NULL; tbl->n++; return true; } }
static int fatfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode) { fatfs_disk_t *disk = (fatfs_disk_t *) fp->f_mte->data; fatfs_fd_t *fd = (fatfs_fd_t *) fp->f_data; fatfs_node_t *node = fd->node; int err; CYG_TRACE2(TFO, "fsync fp=%p mode=%d", fp, mode); err = fatfs_write_dir_entry(disk, &node->dentry); if (ENOERR == err) err = cyg_blib_sync(&disk->blib); return err; }
cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) { cyg_uint32 result; #if (defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)) && \ (defined(CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT) || \ defined(CYGHWR_HAL_GDB_PORT_VECTOR) && \ defined(HAL_CTRLC_ISR)) #ifndef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN #if CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT int gdb_vector = -1; // This check only to avoid crash on older stubs in case of unhandled // interrupts. It is a bit messy, but required in a transition period. #ifndef CYGSEM_HAL_ROM_MONITOR if (CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK == (CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK)) #endif { hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); if (__chan) gdb_vector = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DBG_ISR_VECTOR); } if( CYGHWR_HAL_GDB_PORT_VECTORS_MATCH(vector, gdb_vector) ) #else // Old code using hardwired channels. This should go away eventually. if( vector == CYGHWR_HAL_GDB_PORT_VECTOR ) #endif #endif { result = HAL_CTRLC_ISR( vector, data ); if( 0 != result ) return result; } #endif result = hal_arch_default_isr (vector, data); if( 0 != result) return result; CYG_TRACE2(true, "Interrupt: %d, Data: 0x%08x", vector, data); CYG_FAIL("Spurious Interrupt!!!"); return 0; }
void fatfs_node_free(fatfs_disk_t *disk, fatfs_node_t *node) { CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(node); CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->dentry.filename, node->refcnt); CYG_ASSERTC(node->refcnt == 0); CYG_ASSERTC(node != disk->root); // Remove from dead list, from hash and free ptr node_list_remove(&disk->dead_nlist, node); if (!node_hash_remove(&disk->node_hash, node)) CYG_ASSERT(false, "node not in hash"); node_pool_free(disk, node); SANITY_CHECK(); }
static int fatfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence) { fatfs_disk_t *disk = (fatfs_disk_t *) fp->f_mte->data; fatfs_fd_t *fd = (fatfs_fd_t *) fp->f_data; off_t pos = *apos; int err; CYG_TRACE3(TFO, "lseek fp=%p pos=%d whence=%d", fp, fp->f_offset, whence); switch (whence) { case SEEK_SET: // Pos is already where we want to be break; case SEEK_CUR: // Add pos to current offset pos += fp->f_offset; break; case SEEK_END: // Add pos to file size pos += fd->node->dentry.size; break; default: return EINVAL; } // Check that pos is still within current file size, // or at the very end if (pos < 0 || pos > fd->node->dentry.size) return EINVAL; // All OK, set fp offset and return new position err = fatfs_setpos(disk, &fd->node->dentry, &fd->pos, pos); if (ENOERR == err) *apos = fp->f_offset = pos; CYG_TRACE2(TFO, "lseek fp=%p new pos=%d", fp, *apos); return err; }
void fatfs_node_ref(fatfs_disk_t *disk, fatfs_node_t *node) { CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(node); CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->dentry.filename, node->refcnt); node->refcnt++; if (1 == node->refcnt) { // First reference - move node from dead to live list CYG_TRACE1(TNC, "node='%s' to live list", node->dentry.filename); node_list_remove(&disk->dead_nlist, node); node_list_head_add(&disk->live_nlist, node); } SANITY_CHECK(); }
void fatfs_node_touch(fatfs_disk_t *disk, fatfs_node_t *node) { CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(node); CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->dentry.filename, node->refcnt); if (node->refcnt == 0) { node_list_remove(&disk->dead_nlist, node); node_list_head_add(&disk->dead_nlist, node); } else { node_list_remove(&disk->live_nlist, node); node_list_head_add(&disk->live_nlist, node); } SANITY_CHECK(); }
fatfs_node_t* fatfs_node_alloc(fatfs_disk_t *disk, fatfs_dir_entry_t *dentry) { fatfs_node_t *node; CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(dentry); node = node_pool_alloc(disk); if (NULL == node) { CYG_TRACE2(TNC, "getting node from dead list (size=%d keep=%d)", node_list_get_size(&disk->dead_nlist), DLIST_KEEP_NUM); if (node_list_get_size(&disk->dead_nlist) <= DLIST_KEEP_NUM) return NULL; node = node_list_tail_get(&disk->dead_nlist); if (NULL == node) return NULL; CYG_TRACE1(TNC, "recycling node='%s'", node->dentry.filename); node_list_remove(&disk->dead_nlist, node); if (!node_hash_remove(&disk->node_hash, node)) CYG_ASSERT(false, "node not in hash"); } // Init new node node->dentry = *dentry; node->refcnt = 0; node_list_head_add(&disk->dead_nlist, node); if (!node_hash_add(&disk->node_hash, node)) CYG_ASSERT(false, "node already in hash"); SANITY_CHECK(); return node; }
static fatfs_node_t* node_hash_find(fatfs_hash_table_t *tbl, const char *name, unsigned int namelen, unsigned int parent_cluster) { unsigned int hval; fatfs_node_t *node; // Calculate hash of name and get the first node in slot hval = hash_fn(name, namelen) % tbl->size; node = tbl->nodes[hval]; CYG_TRACE2(TNC, "name='%s' hval=%d\n", name, hval); // Find the node in list wich matches the // given name and parent_cluster while (node != NULL) { // First compare the parent cluster number and // check filename length since it is faster than // comparing filenames if (parent_cluster == node->dentry.parent_cluster && '\0' == node->dentry.filename[namelen]) { int i = strncasecmp(node->dentry.filename, name, namelen); if (i == 0) return node; else if (i > 0) return NULL; // Stop searching - we have a // sorted list so there can't be // any matching filename further on // if i > 0 - look at node_hash_add } node = node->hash_next; } // No such node found return NULL; }
void fatfs_node_unref(fatfs_disk_t *disk, fatfs_node_t *node) { CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(node); CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->dentry.filename, node->refcnt); CYG_ASSERT(node->refcnt > 0, "node->refcnt <= 0"); node->refcnt--; if (0 == node->refcnt) { // No more references - move node from live to dead list CYG_TRACE1(TNC, "node='%s' to dead list", node->dentry.filename); node_list_remove(&disk->live_nlist, node); node_list_head_add(&disk->dead_nlist, node); } SANITY_CHECK(); }
static int fatfs_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence) { fatfs_disk_t *disk = (fatfs_disk_t *) fp->f_mte->data; fatfs_fd_t *fd = (fatfs_fd_t *) fp->f_data; int err; CYG_TRACE2(TFO, "dirlseek fp=%p whence=%d", fp, whence); // Only allow SEEK_SET to zero if (whence != SEEK_SET || *pos != 0) return EINVAL; err = fatfs_setpos(disk, &fd->node->dentry, &fd->pos, 0); if (ENOERR == err) *pos = fp->f_offset = 0; return err; }
static int fatfs_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf) { fatfs_fd_t *fd = (fatfs_fd_t *) fp->f_data; fatfs_node_t *node = fd->node; CYG_TRACE2(TFO, "fstat fp=%p buf=%p", fp, buf); // Fill in the status buf->st_mode = node->dentry.mode; buf->st_ino = (ino_t) node->dentry.cluster; buf->st_dev = 0; buf->st_nlink = 1; buf->st_uid = 0; buf->st_gid = 0; buf->st_size = node->dentry.size; buf->st_atime = node->dentry.atime; buf->st_mtime = node->dentry.mtime; buf->st_ctime = node->dentry.ctime; return ENOERR; }
static int find_entry(fatfs_dirsearch_t *ds) { const char *name = ds->path; const char *n = name; char namelen = 0; int err; if( !S_ISDIR(ds->dir->dentry.mode) ) { CYG_TRACE1(TFS, "entry '%s' not dir", ds->dir->dentry.filename); return ENOTDIR; } // Isolate the next element of the path name while (*n != '\0' && *n != '/') n++, namelen++; // If we terminated on a NUL, set last flag if (*n == '\0') ds->last = true; // Update name in dirsearch object ds->name = name; ds->namelen = namelen; err = find_direntry(ds); if (err != ENOERR) return err; CYG_TRACE2(TFS, "entry '%s' %s", name, (ds->node ? "found" : "not found")); if (ds->node != NULL) return ENOERR; else return ENOENT; }
static int fatfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte) { cyg_io_handle_t dev_h; fatfs_disk_t *disk; fatfs_dir_entry_t root_dentry; Cyg_ErrNo err; CYG_TRACE2(TFS, "mount fste=%p mte=%p", fste, mte); init_fatfs_fds(); CYG_TRACE1(TFS, "looking up disk device '%s'", mte->devname); err = cyg_io_lookup(mte->devname, &dev_h); if (err != ENOERR) return err; disk = (fatfs_disk_t *)malloc(sizeof(fatfs_disk_t)); if (NULL == disk) return ENOMEM; CYG_TRACE0(TFS, "initializing block cache"); disk->bcache_mem = (cyg_uint8 *)malloc(CYGNUM_FS_FAT_BLOCK_CACHE_MEMSIZE); if (NULL == disk->bcache_mem) { free(disk); return ENOMEM; } // FIXME: get block size from disk device err = cyg_blib_io_create(dev_h, disk->bcache_mem, CYGNUM_FS_FAT_BLOCK_CACHE_MEMSIZE, 512, &disk->blib); if (err != ENOERR) { free(disk->bcache_mem); free(disk); return err; } disk->dev_h = dev_h; CYG_TRACE0(TFS, "initializing disk"); err = fatfs_init(disk); if (err != ENOERR) { cyg_blib_delete(&disk->blib); free(disk->bcache_mem); free(disk); return err; } #if TFS print_disk_info(disk); #endif CYG_TRACE0(TFS, "initializing node cache"); fatfs_node_cache_init(disk); CYG_TRACE0(TFS, "initializing root node"); fatfs_get_root_dir_entry(disk, &root_dentry); disk->root = fatfs_node_alloc(disk, &root_dentry); fatfs_node_ref(disk, disk->root); mte->root = (cyg_dir)disk->root; mte->data = (CYG_ADDRWORD)disk; CYG_TRACE0(TFS, "disk mounted"); return ENOERR; }