Пример #1
0
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;
    }
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
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();
}
Пример #5
0
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;
}
Пример #6
0
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();
}
Пример #7
0
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();
}
Пример #8
0
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;
}
Пример #9
0
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; 
}
Пример #10
0
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();
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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; 
}
Пример #14
0
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;
}