Index: trunk/kernel/devices/dev_ioc.c
===================================================================
--- trunk/kernel/devices/dev_ioc.c	(revision 1)
+++ trunk/kernel/devices/dev_ioc.c	(revision 3)
@@ -32,4 +32,5 @@
 #include <thread.h>
 #include <printk.h>
+#include <chdev.h>
 #include <dev_ioc.h>
 
@@ -38,103 +39,69 @@
 /////////////////////////////////////////////////////////////////////////////////////////
 
-extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
+extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
 
-extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
+extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
 
-//////////////////////////////////
-void dev_ioc_init( xptr_t dev_xp )
+////////////////////////////////////
+void dev_ioc_init( chdev_t * chdev )
 {
-    // get IOC device descriptor cluster and local pointer
-    cxy_t      dev_cxy = GET_CXY( dev_xp );
-    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
+    // the local ICU chdev must be initialized before the IOC chdev, because
+    // the IOC chdev initialisation requires allocation of a WTI from local ICU
+    xptr_t  icu_xp  = chdev_dir.icu[local_cxy];
+    assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before IOC" );
 
-    // get implementation from device descriptor
-    uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
+    // get implementation and channel from chdev descriptor
+    uint32_t  impl    = chdev->impl;
+    uint32_t  channel = chdev->channel;
 
-    // set driver specific fields in device descriptor
-    // and call driver init function
+    // set driver specific fields in chdev descriptor and call driver init function
     if( impl == IMPL_IOC_BDV )
     {
-        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_bdv_command );
-        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_bdv_isr );
-        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
-                           XPTR( local_cxy , "IOC_BDV" ) , 16 );
-        soclib_bdv_init( dev_xp );
+        chdev->cmd = &soclib_bdv_cmd;
+        chdev->isr = &soclib_bdv_isr;
+        soclib_bdv_init( chdev );
     }
     else if( impl == IMPL_IOC_HBA )
     {
-        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_hba_command );
-        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_hba_isr );
-        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
-                           XPTR( local_cxy , "IOC_HBA" ) , 16 );
-        soclib_hba_init( dev_xp );
+        chdev->cmd = &soclib_hba_command;
+        chdev->isr = &soclib_hba_isr;
+        soclib_hba_init( chdev );
     }
-//    else if( impl == IMPL_IOC_SDC )
-//    {
-//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_sdc_command );
-//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_sdc_isr );
-//        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
-//                           XPTR( local_cxy , "IOC_SDC" ) , 16 );
-//        soclib_sdc_init( dev_xp );
-//    }
-//    else if( impl == IMPL_IOC_SPI )
-//    {
-//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_spi_command );
-//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_spi_isr );
-//        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
-//                           XPTR( local_cxy , "IOC_SPI" ) , 16 );
-//        soclib_spi_init( dev_xp );
-//    }
-//    else if( impl == IMPL_IOC_RDK )
-//    {
-//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_rdk_command );
-//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_rdk_isr );
-//        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
-//                           XPTR( local_cxy , "IOC_RDK" ) , 16 );
-//        soclib_rdk_init( dev_xp );
-//    }
     else
     {
-        printk("\n[PANIC] in %s: undefined IOC device implementation\n", __FUNCTION__ );
-        hal_core_sleep();
+        assert( false , __FUNCTION__ , "undefined IOC device implementation" );
     }
 
+    // get a WTI mailbox from local ICU
+    uint32_t wti_id = dev_icu_wti_alloc();
+
+    assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" );
+
+    // select a core
+    lid_t lid = cluster_select_local_core();
+
+    // enable WTI IRQ and update WTI interrupt vector
+    dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev );
+
+    // link IOC IRQ to WTI mailbox in PIC component 
+    uint32_t irq_id = chdev_pic_input.ioc[channel];
+    dev_pic_bind_irq( irq_id , local_cxy , wti_id );
+
     // create server thread
-    thread_t * new_thread_ptr;
-    xptr_t     new_thread_xp;
+    thread_t * new_thread;
     error_t    error;
 
-    if( dev_cxy == local_cxy )         // device cluster is local
-    {
-        error = thread_kernel_create( &new_thread_ptr,
-                                      THREAD_DEV,
-                                      &dev_ioc_server,
-                                      dev_ptr,
-                                      cluster_select_local_core() ); 
+    error = thread_kernel_create( &new_thread,
+                                  THREAD_DEV,
+                                  &chdev_sequencial_server,
+                                  chdev,
+                                  lid ); 
+    assert( (error == 0) , __FUNCTION__ , "cannot create server thread" );
 
-        new_thread_xp = XPTR( local_cxy , new_thread_ptr );
-    }
-    else                                    // device cluster is remote
-    {
-        rpc_thread_kernel_create_client( dev_cxy,
-                                         THREAD_DEV,
-                                         &dev_ioc_server,
-                                         dev_ptr,
-                                         &new_thread_xp,
-                                         &error );
-
-        new_thread_ptr = (thread_t *)GET_PTR( new_thread_xp );
-    }
-    if( error )
-    {
-        printk("\n[PANIC] in %s : cannot create server thread\n", __FUNCTION__ );
-        hal_core_sleep();
-    }
-
-    // set "server" field in device descriptor
-    hal_remote_spt( XPTR( dev_cxy , &dev_ptr->server ) , new_thread_ptr );
+    // set "server" field in chdev descriptor
+    chdev->server = new_thread;
     
     // start server thread
-    thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL );
+    thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
  
 }  // end dev_ioc_init()
@@ -144,5 +111,5 @@
 // It builds and registers the command in the calling thread descriptor, after
 // translation of buffer virtual address to physical address. 
-// Then, it registers the calling thead in device waiting queue.
+// Then, it registers the calling thead in chdev waiting queue.
 // Finally it blocks on the THREAD_BLOCKED_DEV condition and deschedule.
 ////////////////////////////////////i/////////////////////////////////////////////
@@ -152,20 +119,18 @@
                                uint32_t  count )
 {
-    thread_t  * this      = CURRENT_THREAD;              // pointer on client thread
-    cxy_t       local_cxy = local_cxy;                   // client thread cluster
+    thread_t * this = CURRENT_THREAD;              // pointer on client thread
 
     error_t     error;
     paddr_t     buf_paddr;
-    bool_t      ident = CONFIG_KERNEL_IDENTITY;
 
     // Get buffer physical address
-    error = vmm_v2p_translate( ident , buffer , &buf_paddr );
+    error = vmm_v2p_translate( CONFIG_KERNEL_IDENTITY , buffer , &buf_paddr );
  
     if( error )  return EINVAL;
 
     ioc_dmsg("\n[INFO] in %s : thread %x in process %x"
-             " for lba = %x / vaddr = %x / paddr = %llx\n", 
+             " for lba = %x / vaddr = %x / paddr = %l / at cycle %d\n", 
              __FUNCTION__ , this->trdid , this->process->pid , 
-             lba , (uint32_t)buffer , buf_paddr );
+             lba , (uint32_t)buffer , buf_paddr , hal_time_stamp() );
 
 #if USE_IOB    // software L2/L3 cache coherence for memory buffer 
@@ -176,55 +141,28 @@
 #endif     // end software L2/L3 cache coherence
 
-    // get extended pointer on IOC device descriptor
-    xptr_t  dev_xp = devices_dir.ioc;
+    // get extended pointer on IOC chdev descriptor
+    xptr_t  dev_xp = chdev_dir.ioc[0];
 
-    if ( dev_xp == XPTR_NULL )
-    {
-        printk("\n[PANIC] in %s : undefined IOC device descriptor\n", __FUNCTION__ );
-        hal_core_sleep();
-    }
+    assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined IOC chdev descriptor" );
 
-    // get a free WTI mailbox  
-    uint32_t wti_id;
-    while( 1 )
-    {
-        wti_id = dev_icu_wti_alloc();
-        if( wti_id == -1 )  sched_yield();
-        else                break;
-    }
+    // register command in calling thread descriptor
+    this->command.ioc.dev_xp    = dev_xp;
+    this->command.ioc.to_mem    = to_mem;
+    this->command.ioc.buf_xp    = XPTR( local_cxy , buffer );
+    this->command.ioc.lba       = lba;
+    this->command.ioc.count     = count;
 
-    // enable WTI IRQ in local ICU and update WTI interrupt vector
-    dev_icu_enable_irq( local_cxy, CURRENT_CORE->lid , WTI_TYPE , wti_id , dev_xp );
-
-    // link IOC IRQ to WTI mailbox in PIC component 
-    uint32_t irq_id = devices_input_irq.ioc; 
-    dev_pic_bind_irq( irq_id , local_cxy , wti_id );
-
-    // store command in thread descriptor
-    this->dev.ioc.dev_xp    = dev_xp;
-    this->dev.ioc.to_mem    = to_mem;
-    this->dev.ioc.buf_xp    = XPTR( local_cxy , buffer );
-    this->dev.ioc.lba       = lba;
-    this->dev.ioc.count     = count;
-
-    // register client thread in waiting queue, activate server thread,
+    // register client thread in IOC chdev waiting queue, activate server thread,
     // block client thread on THREAD_BLOCKED_IO and deschedule.
     // it is re-activated by the ISR signaling IO operation completion.
-    device_register_command( dev_xp , this );
+    chdev_register_command( dev_xp , this );
 
-    // access PIC to unlink the IOC IRQ
-    dev_pic_unbind_irq( irq_id );
-
-    // disable WTI IRQ in ICU and update interrupt vector
-    dev_icu_disable_irq( local_cxy , CURRENT_CORE->lid , WTI_TYPE , wti_id );
-
-    // release  WTI mailbox
-    dev_icu_wti_release( wti_id );
-
-    ioc_dmsg("\n[INFO] in %s : thread %x in process %x completes / error = %d\n", 
-             __FUNCTION__ , this->trdid , this->process->pid , this->dev.ioc.error );
+    ioc_dmsg("\n[INFO] in %s : thread %x in process %x"
+             " completes / error = %d / at cycle %d\n", 
+             __FUNCTION__ , this->trdid , this->process->pid ,
+             this->dev.ioc.error , hal_time_stamp() );
 
     // return I/O operation status
-    return this->dev.ioc.error;  
+    return this->command.ioc.error;  
 
 }  // end dev_ioc_access()
@@ -245,56 +183,2 @@
     return dev_ioc_access( false , buffer , lba , count ); 
 }
-                        
-/////////////////////////////////////
-void dev_ioc_server( device_t * dev )
-{
-    xptr_t     client_xp;    // extended pointer on waiting thread
-    cxy_t      client_cxy;   // cluster of client thread
-    thread_t * client_ptr;   // local pointer on client thread
-    thread_t * server;       // local pointer on server thread
-    xptr_t     root_xp;      // extended pointer on device waiting queue root
-
-    server    = CURRENT_THREAD;
-
-    root_xp   = XPTR( local_cxy , &dev->wait_root );
-
-	// infinite loop handling commands registered in the IOC waiting queue
-    // TODO If we want to implement an "elevator" mecanism (i.e. sort all
-    // pending command on the LBA to optimize physical device accesses),
-    // it should be done in this loop...
-
-    while( 1 )
-    {
-        // get lock protecting queue
-        remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) );
-
-        // block and deschedule server thread if waiting queue empty 
-        if( xlist_is_empty( root_xp ) )
-        {
-            thread_block( server , THREAD_BLOCKED_DEV_QUEUE );
-            remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );
-            sched_yield();
-        }
-        else
-        {
-            remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );
-        } 
-
-        // get extended pointer on first client thread
-        client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
-
-        // call driver command function to start I/O operation
-        dev->cmd( client_xp );
-        
-        // get client thread cluster and local pointer
-        client_cxy = GET_CXY( client_xp );
-        client_ptr = (thread_t *)GET_PTR( client_xp );
-
-        // remove the client thread from waiting queue
-        remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) );
-        xlist_unlink( XPTR( client_cxy , &client_ptr->wait_list ) );
-        remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );
-
-    }  // end while
-
-}  // end dev_ioc_server()
