Index: trunk/kernel/fs/devfs.c
===================================================================
--- trunk/kernel/fs/devfs.c	(revision 610)
+++ trunk/kernel/fs/devfs.c	(revision 612)
@@ -27,4 +27,5 @@
 #include <hal_uspace.h>
 #include <printk.h>
+#include <string.h>
 #include <chdev.h>
 #include <thread.h>
@@ -102,4 +103,8 @@
                                      devfs_dev_inode_xp );
 
+    // create dentries <.> and <..> in <dev>
+    error |= vfs_add_special_dentries( *devfs_dev_inode_xp,
+                                       root_inode_xp );
+
 // check success
 assert( (error == 0) , "cannot create <dev>\n" );
@@ -122,5 +127,10 @@
                                      devfs_external_inode_xp );
 
-    assert( (error == 0) , "cannot create <external>\n" );
+    // create dentries <.> and <..> in <external>
+    error |= vfs_add_special_dentries( *devfs_external_inode_xp,
+                                       *devfs_dev_inode_xp );
+
+// check success
+assert( (error == 0) , "cannot create <external>\n" );
 
 #if DEBUG_DEVFS_INIT
@@ -147,15 +157,24 @@
     uint32_t      channel;
     xptr_t        unused_xp;    // required by add_child_in_parent()
+    error_t       error;
 
     // create "internal" directory 
     snprintf( node_name , 16 , "internal_%x" , local_cxy );
 
-    vfs_add_child_in_parent( local_cxy,
-                             INODE_TYPE_DIR,
-                             FS_TYPE_DEVFS,
-                             devfs_dev_inode_xp,
-                             node_name,
-                             &unused_xp,
-                             devfs_internal_inode_xp );
+    error = vfs_add_child_in_parent( local_cxy,
+                                     INODE_TYPE_DIR,
+                                     FS_TYPE_DEVFS,
+                                     devfs_dev_inode_xp,
+                                     node_name,
+                                     &unused_xp,
+                                     devfs_internal_inode_xp );
+
+    // create dentries <.> and <..> in <internal>
+    error |= vfs_add_special_dentries( *devfs_internal_inode_xp,
+                                       devfs_dev_inode_xp );
+
+// check success
+assert( (error == 0) , "cannot create <external>\n" );
+
 #if DEBUG_DEVFS_INIT 
 uint32_t   cycle = (uint32_t)hal_get_cycles();
@@ -173,14 +192,15 @@
         chdev_cxy = GET_CXY( chdev_xp );
 
-assert( (chdev_cxy == local_cxy ), 
-"illegal MMC chdev_xp in cluster %x\n", local_cxy );
-
-        vfs_add_child_in_parent( local_cxy,
-                                 INODE_TYPE_DEV,
-                                 FS_TYPE_DEVFS,
-                                 *devfs_internal_inode_xp,
-                                 chdev_ptr->name,
-                                 &unused_xp,
-                                 &inode_xp );
+assert( (chdev_cxy == local_cxy ), "illegal MMC chdev in cluster %x\n", local_cxy );
+
+        error = vfs_add_child_in_parent( local_cxy,
+                                         INODE_TYPE_DEV,
+                                         FS_TYPE_DEVFS,
+                                         *devfs_internal_inode_xp,
+                                         chdev_ptr->name,
+                                         &unused_xp,
+                                         &inode_xp );
+
+assert( (error == 0) , "cannot create MMC inode\n" );
 
         // update child inode "extend" field
@@ -207,14 +227,15 @@
             chdev_cxy = GET_CXY( chdev_xp );
 
-assert( (chdev_cxy == local_cxy ), 
-"illegal DMA[%d] chdev_xp in cluster %x\n", channel, local_cxy );
-
-            vfs_add_child_in_parent( local_cxy,
-                                     INODE_TYPE_DEV,
-                                     FS_TYPE_DEVFS,
-                                     *devfs_internal_inode_xp,
-                                     chdev_ptr->name,
-                                     &unused_xp,
-                                     &inode_xp );
+assert( (chdev_cxy == local_cxy ), "illegal DMA chdev in cluster %x\n", local_cxy );
+
+            error = vfs_add_child_in_parent( local_cxy,
+                                             INODE_TYPE_DEV,
+                                             FS_TYPE_DEVFS,
+                                             *devfs_internal_inode_xp,
+                                             chdev_ptr->name,
+                                             &unused_xp,
+                                             &inode_xp );
+
+assert( (error == 0) , "cannot create DMA inode\n" );
 
             // update child inode "extend" field
@@ -241,11 +262,13 @@
         if( chdev_cxy == local_cxy )
         {
-            vfs_add_child_in_parent( local_cxy,
-                                     INODE_TYPE_DEV,
-                                     FS_TYPE_DEVFS,
-                                     devfs_external_inode_xp,
-                                     chdev_ptr->name,
-                                     &unused_xp,
-                                     &inode_xp );
+            error = vfs_add_child_in_parent( local_cxy,
+                                             INODE_TYPE_DEV,
+                                             FS_TYPE_DEVFS,
+                                             devfs_external_inode_xp,
+                                             chdev_ptr->name,
+                                             &unused_xp,
+                                             &inode_xp );
+
+assert( (error == 0) , "cannot create IOB inode\n" );
 
             // update child inode "extend" field
@@ -272,11 +295,13 @@
         if( chdev_cxy == local_cxy )
         {
-            vfs_add_child_in_parent( local_cxy,
-                                     INODE_TYPE_DEV,
-                                     FS_TYPE_DEVFS,
-                                     devfs_external_inode_xp,
-                                     chdev_ptr->name,
-                                     &unused_xp,
-                                     &inode_xp );
+            error = vfs_add_child_in_parent( local_cxy,
+                                             INODE_TYPE_DEV,
+                                             FS_TYPE_DEVFS,
+                                             devfs_external_inode_xp,
+                                             chdev_ptr->name,
+                                             &unused_xp,
+                                             &inode_xp );
+
+assert( (error == 0) , "cannot create PIC inode\n" );
 
             // update child inode "extend" field
@@ -305,11 +330,13 @@
             if( chdev_cxy == local_cxy )
             {
-                vfs_add_child_in_parent( local_cxy,
-                                         INODE_TYPE_DEV,
-                                         FS_TYPE_DEVFS,
-                                         devfs_external_inode_xp,
-                                         chdev_ptr->name,
-                                         &unused_xp,
-                                         &inode_xp );
+                error = vfs_add_child_in_parent( local_cxy,
+                                                 INODE_TYPE_DEV,
+                                                 FS_TYPE_DEVFS,
+                                                 devfs_external_inode_xp,
+                                                 chdev_ptr->name,
+                                                 &unused_xp,
+                                                 &inode_xp );
+
+assert( (error == 0) , "cannot create TXT_RX inode\n" );
 
                 // update child inode "extend" field
@@ -339,11 +366,13 @@
             if( chdev_cxy == local_cxy )
             {
-                vfs_add_child_in_parent( local_cxy,
-                                         INODE_TYPE_DEV,
-                                         FS_TYPE_DEVFS,
-                                         devfs_external_inode_xp,
-                                         chdev_ptr->name,
-                                         &unused_xp,
-                                         &inode_xp );
+                error = vfs_add_child_in_parent( local_cxy,
+                                                 INODE_TYPE_DEV,
+                                                 FS_TYPE_DEVFS,
+                                                 devfs_external_inode_xp,
+                                                 chdev_ptr->name,
+                                                 &unused_xp,
+                                                 &inode_xp );
+
+assert( (error == 0) , "cannot create TXT_TX inode\n" );
 
                 // update child inode "extend" field
@@ -373,11 +402,13 @@
             if( chdev_cxy == local_cxy )
             {
-                vfs_add_child_in_parent( local_cxy,
-                                         INODE_TYPE_DEV,
-                                         FS_TYPE_DEVFS,
-                                         devfs_external_inode_xp,
-                                         chdev_ptr->name,
-                                         &unused_xp,
-                                         &inode_xp );
+                error = vfs_add_child_in_parent( local_cxy,
+                                                 INODE_TYPE_DEV,
+                                                 FS_TYPE_DEVFS,
+                                                 devfs_external_inode_xp,
+                                                 chdev_ptr->name,
+                                                 &unused_xp,
+                                                 &inode_xp );
+
+assert( (error == 0) , "cannot create IOC inode\n" );
 
                 // update child inode "extend" field
@@ -407,11 +438,13 @@
             if( chdev_cxy == local_cxy )
             {
-                vfs_add_child_in_parent( local_cxy,
-                                         INODE_TYPE_DEV,
-                                         FS_TYPE_DEVFS,
-                                         devfs_external_inode_xp,
-                                         chdev_ptr->name,
-                                         &unused_xp,
-                                         &inode_xp );
+                error = vfs_add_child_in_parent( local_cxy,
+                                                 INODE_TYPE_DEV,
+                                                 FS_TYPE_DEVFS,
+                                                 devfs_external_inode_xp,
+                                                 chdev_ptr->name,
+                                                 &unused_xp,
+                                                 &inode_xp );
+
+assert( (error == 0) , "cannot create FBF inode\n" );
 
                 // update child inode "extend" field
@@ -441,11 +474,19 @@
             if( chdev_cxy == local_cxy )
             {
-                vfs_add_child_in_parent( local_cxy,
-                                         INODE_TYPE_DEV,
-                                         FS_TYPE_DEVFS,
-                                         devfs_external_inode_xp,
-                                         chdev_ptr->name,
-                                         &unused_xp,
-                                         &inode_xp );
+                error = vfs_add_child_in_parent( local_cxy,
+                                                 INODE_TYPE_DEV,
+                                                 FS_TYPE_DEVFS,
+                                                 devfs_external_inode_xp,
+                                                 chdev_ptr->name,
+                                                 &unused_xp,
+                                                 &inode_xp );
+
+assert( (error == 0) , "cannot create NIC_RX inode\n" );
+
+                // update child inode "extend" field
+                inode_cxy = GET_CXY( inode_xp );
+                inode_ptr = GET_PTR( inode_xp );
+                hal_remote_spt( XPTR( inode_cxy , &inode_ptr->extend ) , chdev_ptr );
+ 
 #if DEBUG_DEVFS_INIT
 cycle = (uint32_t)hal_get_cycles();
@@ -469,11 +510,13 @@
             if( chdev_cxy == local_cxy )
             {
-                vfs_add_child_in_parent( local_cxy,
-                                         INODE_TYPE_DEV,
-                                         FS_TYPE_DEVFS,
-                                         devfs_external_inode_xp,
-                                         chdev_ptr->name,
-                                         &unused_xp,
-                                         &inode_xp );
+                error = vfs_add_child_in_parent( local_cxy,
+                                                 INODE_TYPE_DEV,
+                                                 FS_TYPE_DEVFS,
+                                                 devfs_external_inode_xp,
+                                                 chdev_ptr->name,
+                                                 &unused_xp,
+                                                 &inode_xp );
+
+assert( (error == 0) , "cannot create NIC_TX inode\n" );
 
                 // update child inode "extend" field
@@ -620,3 +663,73 @@
 }  // end devfs_user_move()
 
-
+///////////////////////////////////////////////////////
+error_t devfs_get_user_dir( struct vfs_inode_s * inode,
+                            struct dirent      * array,
+                            uint32_t             max_dirent,
+                            uint32_t             min_dentry,
+                            bool_t               detailed,
+                            uint32_t           * entries,
+                            bool_t             * done )
+{
+    xptr_t         xhtab_xp;    // extended pointer on inode xhtab (children dentries)
+    xptr_t         dentry_xp;   // extended pointer on current dentry
+    vfs_dentry_t * dentry_ptr;  // local pointer on current dentry
+    uint32_t       dentry_id;   // dentry index in set of children dentry    
+    uint32_t       dirent_id;   // dirent index in array of dirent
+
+// detailed argument unused
+assert( (detailed == false) , "detailed argument not supported\n");
+ 
+    // One loop to scan the target inode xhtab containing the set of dentries
+    // exit loop if no more dentries, or dirent array full 
+
+#if DEBUG_DEVFS_GET_USER_DIR
+char       inode_name[CONFIG_VFS_MAX_NAME_LENGTH];
+uint32_t   cycle = (uint32_t)hal_get_cycles();
+thread_t * this  = CURRENT_THREAD;
+vfs_inode_get_name( XPTR( local_cxy , inode ) , inode_name );
+if( DEBUG_DEVFS_GET_USER_DIR < cycle )
+printk("\n[%s]  thread[%x,%x] enter for inode <%s> / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, inode_name , cycle );
+#endif
+
+    // get extended pointer on inode xhtab 
+    xhtab_xp  = XPTR( local_cxy , &inode->children );
+
+    // initialize loop variables
+    dentry_xp = xhtab_get_first( xhtab_xp );
+    dentry_id = 0;
+    dirent_id = 0;
+
+    while( (dentry_xp != XPTR_NULL ) && (dirent_id < max_dirent) )
+    {
+        if( dentry_id >= min_dentry )
+        {
+            // copy name into dirent array
+            dentry_ptr = GET_PTR( dentry_xp );
+            strcpy( array[dirent_id].d_name , dentry_ptr->name ); 
+
+            // increment dirent_id
+            dirent_id++;
+        }
+         
+        // update loop variables
+        dentry_xp = xhtab_get_next( xhtab_xp );
+        dentry_id++;
+    }
+
+    // return results of scan
+    *done    = (dentry_xp == XPTR_NULL);
+    *entries = dirent_id;
+
+#if DEBUG_DEVFS_GET_USER_DIR
+cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_DEVFS_GET_USER_DIR < cycle )
+printk("\n[%s]  thread[%x,%x] exit for inode <%s> / %d entries / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, inode_name, entries, cycle );
+#endif
+
+    return 0;
+    
+}  // en devfs_get_user_dir()
+
