Index: trunk/kernel/vfs/devfs.c
===================================================================
--- trunk/kernel/vfs/devfs.c	(revision 50)
+++ trunk/kernel/vfs/devfs.c	(revision 188)
@@ -26,628 +26,282 @@
 #include <hal_special.h>
 #include <printk.h>
+#include <chdev.h>
+#include <cluster.h>
+#include <vfs.h>
 #include <kmem.h>
-#include <string.h>
-#include <chdev.h>
-#include <core.h>
-#include <thread.h>
-#include <vfs.h>
-#include <errno.h>
 #include <devfs.h>
-#include <rpc.h>
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//          Extern  variables         
-//////////////////////////////////////////////////////////////////////////////////////////
-
-extern vfs_ctx_t          fs_context[FS_TYPES_NR];   // allocated in vfs.c file
-
-extern remote_barrier_t   global_barrier;            // allocated in kernel_init.c
- 
-extern chdev_directory_t  chdev_dir;                 // allocated in kernel_init.c
-
-////////////////////////////////////////////////////////////////////////////////////////
-//                DEVFS private functions
-////////////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////////////
-// This function creates in the local cluster the dentry and the associated inode,
-// for a DEVFS directory (level 0 or level 1 in DEVFS tree).
-////////////////////////////////////////////////////////////////////////////////////////
-// @ name        : directory entry name.
-// @ parent_xp   : extended pointer on parent inode.
-// @ inode_xp    : [out] buffer for extended pointer on created inode.
-////////////////////////////////////////////////////////////////////////////////////////
-static void devfs_create_directory( char        * name,
-                                    xptr_t        parent_xp,
-                                    xptr_t      * inode_xp )
-{
-    error_t       error;
-    xptr_t        new_dentry_xp;     // extended pointer on created dentry
-    xptr_t        new_inode_xp;      // extended pointer on created inode
- 
-    // get parent inode cluster and local pointer
-    cxy_t         parent_cxy = GET_CXY( parent_xp );
-    vfs_inode_t * parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp );
-
-    // create vfs_dentry in cluster containing the parent inode
-    if( parent_cxy == local_cxy )
-    {
-        error = vfs_dentry_create( FS_TYPE_DEVFS,
-                                   name,
-                                   parent_ptr,
-                                   &new_dentry_xp );
-    }
-    else
-    {
-        rpc_vfs_dentry_create_client( parent_cxy,
-                                      FS_TYPE_DEVFS,
-                                      name,
-                                      parent_ptr,
-                                      &new_dentry_xp,
-                                      &error );
-    }
-
-    if ( error )
-    {
-        printk("\n[PANIC] in %s : cannot create dentry for %s in cluster %x/n",
-               __FUNCTION__ , name , local_cxy );
-        hal_core_sleep();
-    }
-
-    // create vfs_inode in local cluster TODO define the 4 arguments below [AG]
-    uint32_t  attr   = 0;
-    uint32_t  rights = 0;
-    uid_t     uid    = 0;
-    gid_t     gid    = 0;
-    error = vfs_inode_create( new_dentry_xp,
-                              FS_TYPE_DEVFS,
-                              INODE_TYPE_DIR,
-                              attr,
-                              rights,
-                              uid,
-                              gid,
-                              &new_inode_xp );
-    if( error )
-    {
-        printk("\n[PANIC] in %s : cannot create inode for %s in cluster %x/n",
-               __FUNCTION__ , name , local_cxy );
-        hal_core_sleep();
-    }
-
-    // return extended pointer on directory inode
-    *inode_xp = new_inode_xp;
-
-}  // end devfs_create_directory()
-                                    
-////////////////////////////////////////////////////////////////////////////////////////
-// This function creates in the local cluster the dentry and the associated inode,
-// for a chdev (level 2 in DEVFS tree).
-////////////////////////////////////////////////////////////////////////////////////////
-// @ chdev    : local pointer on local chdev.
-// @ name     : directory entry name.
-// @ parent   : local pointer on local parent inode.
-// @ inode_xp : [out] buffer for extended pointer on created inode.
-////////////////////////////////////////////////////////////////////////////////////////
-static void devfs_register_chdev( chdev_t     * chdev,
-                                  char        * name,
-                                  vfs_inode_t * parent,
-                                  xptr_t      * inode_xp )
+
+/////////////////////////////////////////////////////////////////////////////////////////
+//     Extern variables
+/////////////////////////////////////////////////////////////////////////////////////////
+
+extern vfs_ctx_t            fs_context[];   // allocated in kernel_init.c
+extern chdev_directory_t    chdev_dir;      // allocated in kernel_init.c
+
+///////////////////////////////
+devfs_ctx_t * devfs_ctx_alloc()
+{
+    kmem_req_t    req;
+
+	req.type    = KMEM_DEVFS_CTX;
+	req.size    = sizeof(devfs_ctx_t);
+    req.flags   = AF_KERNEL | AF_ZERO;
+
+	return (devfs_ctx_t *)kmem_alloc( &req );
+}
+
+/////////////////////////////////////////////
+void devfs_ctx_init( devfs_ctx_t * devfs_ctx,
+                     xptr_t        devfs_root_inode_xp,
+                     xptr_t        devfs_external_inode_xp )
+{
+    devfs_ctx->root_inode_xp     = devfs_root_inode_xp;
+    devfs_ctx->external_inode_xp = devfs_external_inode_xp;
+
+    fs_context[FS_TYPE_DEVFS].extend = devfs_ctx;
+}
+
+/////////////////////////////////////////////////
+void devfs_ctx_destroy( devfs_ctx_t * devfs_ctx )
+{
+    kmem_req_t    req;
+
+    req.type = KMEM_DEVFS_CTX;
+    req.ptr  = devfs_ctx;
+    kmem_free( &req );
+}
+
+///////////////////////////////////////////////////
+void devfs_global_init( xptr_t   parent_inode_xp,
+                        xptr_t * devfs_root_inode_xp,
+                        xptr_t * devfs_external_inode_xp )
 {
     error_t  error;
-    xptr_t   new_dentry_xp;
-    xptr_t   new_inode_xp;
-
-    devfs_dmsg("\n[INFO] %s : create dentry for %s\n", __FUNCTION__ , name );
-    
-    // create vfs_dentry in local cluster
-    error = vfs_dentry_create( FS_TYPE_DEVFS,
-                               name,
-                               parent,
-                               &new_dentry_xp );
-    if ( error )
-    {
-        printk("\n[PANIC] in %s : cannot create dentry for %s in cluster %x/n",
-               __FUNCTION__ , name , local_cxy );
-        hal_core_sleep();
-    }
-
-    devfs_dmsg("\n[INFO] %s : create inode for %s\n", __FUNCTION__ , name );
-    
-    // create vfs_inode in local cluster
-    uint32_t  attr   = 0;
-    uint32_t  rights = 0;
-    uid_t     uid    = 0;
-    gid_t     gid    = 0;
-    error = vfs_inode_create( new_dentry_xp,
-                              FS_TYPE_DEVFS,
-                              INODE_TYPE_DEV,
-                              attr,
-                              rights,
-                              uid,
-                              gid,
-                              &new_inode_xp );
-    if( error )
-    {
-        printk("\n[PANIC] in %s : cannot create inode for %s in cluster %x/n",
-               __FUNCTION__ , name , local_cxy );
-        hal_core_sleep();
-    }
-
-    // return extended pointer on chdev inode
-    *inode_xp = new_inode_xp;
-    
-}  // end devfs_register_chdev()
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////
-// Generic API : the following functions are called by the VFS, 
-//               and must be defined by all supported file systems.
-///////////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////
-
-////////////////////////////////////////////
-error_t devfs_mount( xptr_t   parent_inode_xp,
-                     char   * devfs_root_name )
-{
-    assert( (CURRENT_CORE->lid == 0) , __FUNCTION__ , "only CP0 should do it" );
-
-    vfs_inode_t * parent_inode_ptr;
-    cxy_t         parent_inode_cxy;
-    vfs_ctx_t   * vfs_ctx;
-
+
+    // creates DEVFS "dev" inode in cluster IO
+    error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy,
+                                     INODE_TYPE_DIR,
+                                     FS_TYPE_DEVFS,
+                                     parent_inode_xp,
+                                     "dev",
+                                     NULL,
+                                     devfs_root_inode_xp ); 
+
+    nolock_assert( (error == 0) , __FUNCTION__ , "cannot create <dev>\n" );
+
+    // create DEVFS "external" inode in cluster IO
+    error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy,
+                                     INODE_TYPE_DIR,
+                                     FS_TYPE_DEVFS,
+                                     *devfs_root_inode_xp,
+                                     "dev",
+                                     NULL,
+                                     devfs_external_inode_xp ); 
+
+    nolock_assert( (error == 0) , __FUNCTION__ , "cannot create <external>\n" );
+} 
+
+//////////////////////////////////////////////////
+void devfs_local_init( xptr_t devfs_root_inode_xp,
+                       xptr_t devfs_external_inode_xp )
+{
     char          node_name[16];
+    xptr_t        chdev_xp;
+    cxy_t         chdev_cxy;
+    xptr_t        inode_xp;
+    xptr_t        internal_inode_xp;
     uint32_t      channel;
 
-    xptr_t        root_inode_xp;
-    xptr_t        external_inode_xp;
-    xptr_t        internal_inode_xp;
-    xptr_t        chdev_inode_xp;
-
-    chdev_t     * chdev_ptr;
-
-    // get number of kernel instances and extended pointer on global barrier 
-    cluster_t * cluster     = LOCAL_CLUSTER;
-    uint32_t    nb_clusters = cluster->x_size * cluster->y_size;
-    xptr_t      barrier_xp  = XPTR( cluster->io_cxy , &global_barrier );
-
-    // get VFS root inode cluster and local pointer
-    parent_inode_cxy = GET_CXY( parent_inode_xp );
-    parent_inode_ptr = (vfs_inode_t *)GET_PTR( parent_inode_xp );
-
-    // get local pointer on VFS context for DEVFS
-    vfs_ctx = &fs_context[FS_TYPE_DEVFS];
-
-    ///// step 1 : all clusters initialize local DEVFS context  /////
-
-    devfs_ctx_init( vfs_ctx , parent_inode_xp );
-
-    ///// step 2 : cluster_0 creates DEVFS root    /////
-
-    if( local_cxy == 0 )
-    {
-        devfs_create_directory( devfs_root_name,
-                                parent_inode_xp,
-                                &root_inode_xp );
-    }
-
-    // synchronize all clusters
-    remote_barrier( barrier_xp , nb_clusters );
-
-    ///// step 3 : all clusters create "internal" directory and chdevs  /////
-
-    // TODO check device existence : (chdev_xp != XPTR_NULL) in chdev_dir
-
+    // create "internal" directory linked to "dev"
     snprintf( node_name , 16 , "internal_%x" , local_cxy );
-
-    devfs_create_directory( node_name,
-                            root_inode_xp,
-                            &internal_inode_xp );
+    vfs_add_child_in_parent( local_cxy,
+                             INODE_TYPE_DIR,
+                             FS_TYPE_DEVFS,
+                             devfs_root_inode_xp,
+                             node_name,
+                             NULL,
+                             &internal_inode_xp );
 
     // create ICU chdev inode
-    chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.icu[local_cxy] );
-    devfs_register_chdev( chdev_ptr,
-                          "icu",
-                          (vfs_inode_t *)GET_PTR( internal_inode_xp ),
-                          &chdev_inode_xp );
+    chdev_xp = chdev_dir.icu[local_cxy];
+    if( chdev_xp != XPTR_NULL) 
+    {
+        vfs_add_child_in_parent( local_cxy,
+                                 INODE_TYPE_DEV,
+                                 FS_TYPE_DEVFS,
+                                 internal_inode_xp,
+                                 "icu",
+                                 GET_PTR( chdev_xp ),
+                                 &inode_xp );
+    }
 
     // create MMC chdev inode
-    chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.mmc[local_cxy] );
-    devfs_register_chdev( chdev_ptr,
-                          "mmc", 
-                          (vfs_inode_t *)GET_PTR( internal_inode_xp ),
-                          &chdev_inode_xp );
+    chdev_xp = chdev_dir.mmc[local_cxy];
+    if( chdev_xp != XPTR_NULL)
+    {
+        vfs_add_child_in_parent( local_cxy,
+                                 INODE_TYPE_DEV,
+                                 FS_TYPE_DEVFS,
+                                 internal_inode_xp,
+                                 "mmc",
+                                 GET_PTR( chdev_xp ),
+                                 &inode_xp );
+    }
 
     // create DMA chdev inodes (one DMA channel per core)
-    for( channel = 0 ; channel < cluster->cores_nr ; channel++ )
-    {
-        chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.dma[channel] );
-        snprintf( node_name , 16 , "dma_%d" , channel );
-        devfs_register_chdev( chdev_ptr,
-                              node_name,
-                              (vfs_inode_t *)GET_PTR( internal_inode_xp ),
-                              &chdev_inode_xp );
-    }
-
-    ///// step 4 : cluster_io creates "external" directory and chdevs /////
-
-    // TODO check device existence : (chdev_xp != XPTR_NULL) in chdev_dir
-
-    if( local_cxy == cluster->io_cxy )
-    {
-        devfs_create_directory( "external",
-                                root_inode_xp,
-                                &external_inode_xp );
-
-        // create IOB chdev inode
-        chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.iob );
-        devfs_register_chdev( chdev_ptr,
-                              "iob",
-                              (vfs_inode_t *)GET_PTR( external_inode_xp ),
-                              &chdev_inode_xp );
+    for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ )
+    {
+        chdev_xp = chdev_dir.dma[channel];
+        if( chdev_xp != XPTR_NULL)
+        {
+            snprintf( node_name , 16 , "dma_%d" , channel );
+            vfs_add_child_in_parent( local_cxy,
+                                     INODE_TYPE_DEV,
+                                     FS_TYPE_DEVFS,
+                                     internal_inode_xp,
+                                     node_name,
+                                     GET_PTR( chdev_xp ),
+                                     &inode_xp );
+        }
+    }
+
+    // create an IOB inode in cluster containing IOB chdev
+    chdev_xp = chdev_dir.iob;
+    if( chdev_xp != XPTR_NULL )
+    {
+        chdev_cxy = GET_CXY( chdev_xp );
+        if( chdev_cxy == local_cxy )
+        {
+            vfs_add_child_in_parent( local_cxy,
+                                     INODE_TYPE_DEV,
+                                     FS_TYPE_DEVFS,
+                                     devfs_external_inode_xp,
+                                     "iob",
+                                     GET_PTR( chdev_xp ),
+                                     &inode_xp );
+        }
+    }
         
-        // create PIC chdev inode
-        chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.pic );
-        devfs_register_chdev( chdev_ptr,
-                              "pic",
-                              (vfs_inode_t *)GET_PTR( external_inode_xp ),
-                              &chdev_inode_xp );
-
-        // create TXT chdev inodes
-        for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
-        {
-            chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.txt[channel] );
-            snprintf( node_name , 16 , "txt_%d" , channel );
-            devfs_register_chdev( chdev_ptr,
-                                  node_name,
-                                  (vfs_inode_t *)GET_PTR( external_inode_xp ),
-                                  &chdev_inode_xp );
-        }
-
-        // create IOC chdev inodes
-        for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
-        {
-            chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.ioc[channel] );
-            snprintf( node_name , 16 , "ioc_%d" , channel );
-            devfs_register_chdev( chdev_ptr,
-                                  node_name,
-                                  (vfs_inode_t *)GET_PTR( external_inode_xp ),
-                                  &chdev_inode_xp );
-        }
-
-        // create FBF chdev inodes
-        for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
-        {
-            chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.ioc[channel] );
-            snprintf( node_name , 16 , "fbf_%d" , channel );
-            devfs_register_chdev( chdev_ptr,
-                                  node_name,
-                                  (vfs_inode_t *)GET_PTR( external_inode_xp ),
-                                  &chdev_inode_xp );
-        }
-
-        // create NIC_RX chdevs
-        for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
-        {
-            chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.nic_rx[channel] );
-            snprintf( node_name , 16 , "nic_rx_%d" , channel );
-            devfs_register_chdev( chdev_ptr,
-                                  node_name,
-                                  (vfs_inode_t *)GET_PTR( external_inode_xp ),
-                                  &chdev_inode_xp );
-        }
-
-        // create NIC_TX chdev inodes
-        for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
-        {
-            chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.nic_tx[channel] );
-            snprintf( node_name , 16 , "nic_tx_%d" , channel );
-            devfs_register_chdev( chdev_ptr,
-                                  node_name,
-                                  (vfs_inode_t *)GET_PTR( external_inode_xp ),
-                                  &chdev_inode_xp );
-        }
-    }
-
-    // synchronize all clusters
-    remote_barrier( barrier_xp , nb_clusters );
-
-    return 0;
-
-}  // end devfs_init()
-
-
-////////////////////////////////////////////
-error_t devfs_ctx_init( vfs_ctx_t * vfs_ctx,
-                        xptr_t      root_inode_xp )
-{
-    vfs_ctx->type    = FS_TYPE_DEVFS;
-    vfs_ctx->attr    = 0;                // not READ_ONLY / not SYNC
-    vfs_ctx->count   = 0;                // unused for DEVFS
-    vfs_ctx->blksize = 0;                // unused for DEVFS
-    vfs_ctx->root_xp = root_inode_xp;
-    vfs_ctx->extend  = NULL;             // unused for DEVFS
-
-    spinlock_init( &vfs_ctx->lock );
-
-    bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES );
-
-    return 0;
-}
-
-
-////////////////////////////////////////////////////
-error_t devfs_inode_create( vfs_inode_t * vfs_inode,
-                            chdev_t     * chdev )
-{
-    kmem_req_t      req;
-    devfs_inode_t * devfs_inode;
-
-    // allocate memory for FATFS inode extension
-	req.type    = KMEM_DEVFS_INODE;
-	req.size    = sizeof(devfs_inode_t);
-    req.flags   = AF_KERNEL | AF_ZERO;
-	devfs_inode = (devfs_inode_t *)kmem_alloc( &req );
-
-    if( devfs_inode == NULL ) return ENOMEM;
-
-    // link DEVFS inode to VFS inode
-    vfs_inode->extend = devfs_inode;
-
-    // initialise DEVFS inode  
-    devfs_inode->chdev = chdev;
- 
-    return 0;
-}
-
-///////////////////////////////////////////////////
-void devfs_inode_destroy( vfs_inode_t * vfs_inode )
-{
-    kmem_req_t      req;
-    devfs_inode_t * devfs_inode;
-
-    // get pointer on DEVFS inode 
-    devfs_inode = (devfs_inode_t *)vfs_inode->extend;
-
-    req.type = KMEM_DEVFS_INODE;
-    req.ptr  = devfs_inode;
-    kmem_free( &req );
-
-	vfs_inode->extend = NULL;
-}
-
-
-/* deprecated [AG]
-
-error_t devfs_open_file( vfs_file_t * file,
-                         void       * extend );
-{
-	error_t err;
-	register struct devfs_context_s *ctx;
-	register struct devfs_file_s *info;
-	chdev_t       * chdev;
-	vfs_inode_t   * inode;
-	dev_request_t   rq;
-	kmem_req_t      req;
-
-	inode = file->inode;
-
-	info = file->fr_pv;
-	ctx  = (struct devfs_context_s *)&inode->i_ctx->ctx_devfs;
-
-	if(!(inode->i_attr & VFS_DIR))
-	{
-		dev = (struct device_s*)inode->i_pv;
-    
-		if(dev->type == DEV_INTERNAL)
-			return EPERM;
-
-		if(dev->type == DEV_BLK)
-			VFS_SET(inode->i_attr,VFS_DEV_BLK);
-		else
-			VFS_SET(inode->i_attr,VFS_DEV_CHR);
- 
-		if(dev->op.dev.open != NULL)
-		{
-			rq.fremote = file;
-			if((err=dev->op.dev.open(dev, &rq)))
-				return err;
-		}
-
-		priv->dev = (void*)dev;
-
-		return 0;
-	}
-
-	if(info == NULL)
-	{
-		req.type  = KMEM_DEVFS_FILE;
-		req.size  = sizeof(*info);
-		req.flags = AF_KERNEL;
-		info      = kmem_alloc(&req);
-	}
-
-	if(info == NULL) return ENOMEM;
-
-	metafs_iter_init(&devfs_db.root, &info->iter);
-	info->ctx  = ctx;
-	file->fr_pv = info;
-  
-	metafs_print(&devfs_db.root);
-	return 0;
-}
-
-#define TMP_BUFF_SZ 512
-
-//FIXME:
-//add a "while" loop for the case where the
-//buffer TMP_BUFF_SZ is smaller than
-//buffer->size
-//////////////////////////////
-devfs_read( vfs_file_t * file,
-            char       * buffer )
-{
-	chdev_t       * chdev;
-	dev_request_t   rq;
-	uint32_t        count;
-    uint8_t         buff[TMP_BUFF_SZ];
-
-    // get pointer on chdev
-	chdev = (chdev_t *)file->extend;
-
-    if( chdev->func == DEV_FUNC_TXT )
-    {
-    }
-    if( chdev->func == DEV_FUNC_IOC )
-    {
-    }
-    else
-    {
-        printk("\n[PANIC] in %s : illegal device functionnal type
-
-	rq.dst   = &buff[0];
-	rq.count = TMP_BUFF_SZ;
-	rq.flags = 0;
-	rq.file  = file;
-
-	if((count = dev->op.dev.read(dev, &rq)) < 0)
-		return count;
-
-        buffer->scpy_to_buff(buffer, &buff[0], count);
-	return count;
-}
-
-//FIXME: To improve this an avoid the extra copy,
-//we could set along with the buffer(src and dest) 
-//the functions to manipulate them, such as in 
-//do_exec.c
-///////////////////////////////
-devfs_write( vfs_file_t * file,
-             char       * buffer )
-{
-	register struct device_s *dev;
-	uint8_t buff[TMP_BUFF_SZ];
-	dev_request_t rq;
-	
-	dev = (struct device_s*)file->f_private.dev;
-	
-	//FIXME avoid the extra copy ?
-	buffer->scpy_from_buff(buffer, (void*)&buff[0], TMP_BUFF_SZ);
-	rq.src   = (void*)&buff[0];
-	rq.count = buffer->size;
-	rq.flags = 0;
-	rq.file  = file;
-  
-	return dev->op.dev.write(dev, &rq);
-}
-
-VFS_LSEEK_FILE(devfs_lseek)
-{
-	register struct device_s *dev;
-	dev_request_t rq;
-
-	dev = (struct device_s*)file->fr_inode->i_pv;
-
-	if(dev->op.dev.lseek == NULL)
-		return VFS_ENOTUSED;
-  
-	rq.fremote = file;
-	return dev->op.dev.lseek(dev, &rq);
-}
-
-VFS_CLOSE_FILE(devfs_close)
-{
-	register struct device_s *dev;
-	dev_request_t rq;
-
-	if(file->fr_inode->i_attr & VFS_DIR)
-		return 0;
-
-	dev = (struct device_s*)file->fr_inode->i_pv;
-
-	if(dev->op.dev.close == NULL)
-		return 0;
-  
-	rq.fremote = file;
-	return dev->op.dev.close(dev, &rq);
-}
-
-VFS_RELEASE_FILE(devfs_release)
-{  
-	kmem_req_t req;
-
-	if(file->fr_pv == NULL) 
-		return 0;
-  
-	req.type = KMEM_DEVFS_FILE;
-	req.ptr  = file->fr_pv;
-	kmem_free(&req);
-
-	file->fr_pv = NULL;
-	return 0;
-}
-
-VFS_READ_DIR(devfs_readdir)
-{
-	register struct devfs_file_s *info;
-	register struct metafs_s *current;
-	register struct device_s *current_dev;
-  
-	info = file->fr_pv;
-  
-	if(file->fr_pv == NULL)
-		return ENOTDIR;
-
-	if((current = metafs_lookup_next(&devfs_db.root, &info->iter)) == NULL)
-		return EEODIR;
-
-	current_dev    = metafs_container(current, struct device_s, node);
-	dirent->u_attr = (current_dev->type == DEV_BLK) ? VFS_DEV_BLK : VFS_DEV_CHR;
-
-	strcpy((char*)dirent->u_name, metafs_get_name(current));
-
-	dirent->u_ino = (uint_t) current_dev->base_paddr;
-
-	return 0;
-}
-
-VFS_MMAP_FILE(devfs_mmap)
-{
-	register struct device_s *dev;
-	dev_request_t rq;
-  
-	dev = (struct device_s*)file->f_private.dev;
-
-	if(dev->op.dev.mmap == NULL)
-		return ENODEV;
-
-	rq.flags  = 0;
-	rq.file   = file;
-	rq.region = region;
-
-	return dev->op.dev.mmap(dev, &rq);
-}
-
-VFS_MMAP_FILE(devfs_munmap)
-{
-	register struct device_s *dev;
-	dev_request_t rq;
-
-	dev = (struct device_s*)file->f_private.dev;
-
-	if(dev->op.dev.munmap == NULL)
-		return ENODEV;
-
-	rq.flags  = 0;
-	rq.file   = file;
-	rq.region = region;
-
-	return dev->op.dev.munmap(dev, &rq);
-}
-
-
-*/
-
-
+    // create a PIC inode in cluster containing PIC chdev
+    chdev_xp = chdev_dir.pic;
+    if( chdev_xp != XPTR_NULL )
+    {
+        chdev_cxy = GET_CXY( chdev_xp );
+        if( chdev_cxy == local_cxy )
+        {
+            vfs_add_child_in_parent( local_cxy,
+                                     INODE_TYPE_DEV,
+                                     FS_TYPE_DEVFS,
+                                     devfs_external_inode_xp,
+                                     "pic",
+                                     GET_PTR( chdev_xp ),
+                                     &inode_xp );
+        }
+    }
+
+    // create a TXT inode in each cluster containing a TXT chdev
+    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
+    {
+        chdev_xp = chdev_dir.txt[channel];
+        if( chdev_xp != XPTR_NULL )
+        {
+            chdev_cxy = GET_CXY( chdev_xp );
+            if( chdev_cxy == local_cxy )
+            {
+                snprintf( node_name , 16 , "txt_%d" , channel );
+                vfs_add_child_in_parent( local_cxy,
+                                         INODE_TYPE_DEV,
+                                         FS_TYPE_DEVFS,
+                                         devfs_external_inode_xp,
+                                         node_name,
+                                         GET_PTR( chdev_xp ),
+                                         &inode_xp );
+            }
+        }
+    }
+
+    // create an IOC inode in each cluster containing an IOC chdev 
+    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
+    {
+        chdev_xp = chdev_dir.ioc[channel];
+        if( chdev_xp != XPTR_NULL )
+        {
+            chdev_cxy = GET_CXY( chdev_xp );
+            if( chdev_cxy == local_cxy )
+            {
+                snprintf( node_name , 16 , "ioc_%d" , channel );
+                vfs_add_child_in_parent( local_cxy,
+                                         INODE_TYPE_DEV,
+                                         FS_TYPE_DEVFS,
+                                         devfs_external_inode_xp,
+                                         node_name,
+                                         GET_PTR( chdev_xp ),
+                                         &inode_xp );
+            }
+        }
+    }
+
+    // create a FBF inode in each cluster containing a FBF chdev
+    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
+    {
+        chdev_xp = chdev_dir.fbf[channel];
+        if( chdev_xp != XPTR_NULL )
+        {
+            chdev_cxy = GET_CXY( chdev_xp );
+            if( chdev_cxy == local_cxy )
+            {
+                snprintf( node_name , 16 , "fbf_%d" , channel );
+                vfs_add_child_in_parent( local_cxy,
+                                         INODE_TYPE_DEV,
+                                         FS_TYPE_DEVFS,
+                                         devfs_external_inode_xp,
+                                         node_name,
+                                         GET_PTR( chdev_xp ),
+                                         &inode_xp );
+            }
+        }
+    }
+
+    // create a NIC_RX inode in each cluster containing a NIC_RX chdev 
+    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
+    {
+        chdev_xp = chdev_dir.nic_rx[channel];
+        if( chdev_xp != XPTR_NULL )
+        {
+            chdev_cxy = GET_CXY( chdev_xp );
+            if( chdev_cxy == local_cxy )
+            {
+                snprintf( node_name , 16 , "nic_rx_%d" , channel );
+                vfs_add_child_in_parent( local_cxy,
+                                         INODE_TYPE_DEV,
+                                         FS_TYPE_DEVFS,
+                                         devfs_external_inode_xp,
+                                         node_name,
+                                         GET_PTR( chdev_xp ),
+                                         &inode_xp );
+            }
+        }
+    }
+
+    // create a NIC_TX inode in each cluster containing a NIC_TX chdev 
+    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
+    {
+        chdev_xp = chdev_dir.nic_tx[channel];
+        if( chdev_xp != XPTR_NULL )
+        {
+            chdev_cxy = GET_CXY( chdev_xp );
+            if( chdev_cxy == local_cxy )
+            {
+                snprintf( node_name , 16 , "nic_tx_%d" , channel );
+                vfs_add_child_in_parent( local_cxy,
+                                         INODE_TYPE_DEV,
+                                         FS_TYPE_DEVFS,
+                                         devfs_external_inode_xp,
+                                         node_name,
+                                         GET_PTR( chdev_xp ),
+                                         &inode_xp );
+            }
+        }
+    }
+}  // end devfs_local_init()
+
