Index: soft/giet_vm/giet_drivers/ioc_driver.c
===================================================================
--- soft/giet_vm/giet_drivers/ioc_driver.c	(revision 279)
+++ soft/giet_vm/giet_drivers/ioc_driver.c	(revision 289)
@@ -1,6 +1,7 @@
 ///////////////////////////////////////////////////////////////////////////////////
-// File     : ioc_driver.c
-// Date     : 23/05/2013
-// Author   : alain greiner
+// File       : ioc_driver.c
+// Date       : 23/05/2013
+// Author     : alain greiner
+// Maintainer : cesar fuguet
 // Copyright (c) UPMC-LIP6
 ///////////////////////////////////////////////////////////////////////////////////
@@ -12,32 +13,25 @@
 //
 // The _ioc_read() and _ioc_write() functions use the _ioc_access() function,
-// that is always blocking, but can be called in 4 modes:
-//
-// - In BOOT_PA mode, the _ioc_access() function use the buffer virtual address 
-//   as a physical address (as the page tables are not build) and use a polling
-//   policy on the IOC_STATUS register to detect transfer completion, as
-//   hardware interrupts are not activated. This mode is used by the
-//   boot code to load the map.bin file into memory.
+// that is always blocking. The _ioc_access function will call the read or
+// write function in the driver of the choosen IOC peripheral, which can be for
+// now: BDV, HBA and SPI. This function can be called in 4 modes:
+//
+// - In BOOT_PA mode, the _ioc_access() function use the buffer virtual address
+//   as a physical address (as the page tables are not build). This mode is
+//   used by the boot code to load the map.bin file into memory.
 //
 // - In BOOT_VA mode, the _ioc_access() function makes a V2P translation to
-//   compute the buffer physical address, and use a polling policy on IOC_STATUS
-//   register to detect transfer completion. This mode is used by the boot code
-//   to load the various .elf files into memory.
+//   compute the buffer physical address. This mode is used by the boot code to
+//   load the various .elf files into memory.
 //
 // - In KERNEL mode, the _ioc_access() function makes a V2P translation to
-//   compute the buffer physical address, and use a descheduling strategy:
-//   The ISR executed when transfer completes should restart the calling task. 
-//   There is no checking of user access right to the memory buffer.
-//   This mode must be used to access IOC, for an "open" system call.
+//   compute the buffer physical address. There is no checking of user access
+//   right to the memory buffer.  This mode must be used to access IOC, for an
+//   "open" system call.
 //
 // - In USER mode, the _ioc_access() function makes a V2P translation to
-//   compute the buffer physical address, and use a descheduling strategy:
-//   The ISR executed when transfer completes should restart the calling task, 
-//   The user access right to the memory buffer must be checked.
-//   This mode must be used to access IOC, for a "read/write" system call.
-//
-// As the IOC component can be used by several programs running in parallel,
-// the _ioc_lock variable guaranties exclusive access to the device.  The
-// _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock.
+//   compute the buffer physical address. The user access right to the memory
+//   buffer must be checked.  This mode must be used to access IOC, for a
+//   "read/write" system call.
 //
 // The IOMMU can be activated or not:
@@ -87,10 +81,27 @@
 #endif
 
+#if (USE_BDV + USE_SPI + USE_HBA) != 1
+# error: You must use only one IOC controller (BDV or SPI or HBA)
+#endif
+
+#if USE_BDV
+# include <bdv_driver.h>
+#endif
+
+#if USE_SPI
+# include <sdc_driver.h>
+#endif
+
+#if USE_HBA
+# include <hba_driver.h>
+#endif
+
+
 #define in_unckdata __attribute__((section (".unckdata")))
 
 ///////////////////// IOC global variables
 
-in_unckdata unsigned int          _ioc_lock = 0;
-in_unckdata volatile unsigned int _ioc_status = 0;
+in_unckdata unsigned int _ioc_lock = 0;
+in_unckdata unsigned int _ioc_status = 0;
 in_unckdata volatile unsigned int _ioc_gtid;
 in_unckdata volatile unsigned int _ioc_iommu_ix1 = 0;
@@ -155,6 +166,4 @@
     }
 
-    volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ;
-
     unsigned int length = count << 9;  // count * 512 bytes
 
@@ -269,117 +278,15 @@
     }
 
-    // get the lock protecting IOC
-    _get_lock(&_ioc_lock);
-
-    // set the _ioc_status polling variable
-    _ioc_status = BLOCK_DEVICE_BUSY;
-
-#if GIET_DEBUG_IOC_DRIVER
-_tty_get_lock( 0 );
-_puts("\n[IOC DEBUG] _ioc_access() : configure IOC\n");
-_puts(" - buf_paddr = ");
-_putl( buf_paddr );
-_puts("\n");
-_puts(" - count     = ");
-_putd( count );
-_puts("\n");
-_puts(" - lba       = ");
-_putx( lba );
-_puts("\n");
-_tty_release_lock( 0 );
-#endif
-
-    // send command to IOC   
-    if ( GIET_USE_IOMMU ) 
-    {
-        ioc_address[BLOCK_DEVICE_BUFFER] = buf_xaddr;
-        ioc_address[BLOCK_DEVICE_COUNT]  = count;
-        ioc_address[BLOCK_DEVICE_LBA]    = lba;
-    }
-    else
-    {
-        ioc_address[BLOCK_DEVICE_BUFFER]     = (unsigned int)buf_paddr;
-        ioc_address[BLOCK_DEVICE_BUFFER_EXT] = (unsigned int)(buf_paddr>>32);
-        ioc_address[BLOCK_DEVICE_COUNT]      = count;
-        ioc_address[BLOCK_DEVICE_LBA]        = lba;
-    }
-
-    // There is two policies for transfer completion 
-	// detection, depending on the mode argument:
-
-    if ( (mode == IOC_BOOT_PA_MODE) ||    // We poll directly the IOC_STATUS register
-         (mode == IOC_BOOT_VA_MODE) )     // as IRQs are masked.
-    {
-        // Launch transfert
-        if (to_mem == 0) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;
-        else             ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;
-
-        unsigned int status;
-        if ( _ioc_get_status(0, &status) ) return 1;
-
-        while( (status != BLOCK_DEVICE_READ_SUCCESS)  &&
-               (status != BLOCK_DEVICE_READ_ERROR)    &&
-               (status != BLOCK_DEVICE_WRITE_SUCCESS) &&
-               (status != BLOCK_DEVICE_WRITE_ERROR) ) 
-        {
-            if ( _ioc_get_status(0, &status) ) return 1;
-
-#if GIET_DEBUG_IOC_DRIVER
-_tty_get_lock( 0 );
-_puts("\n[IOC DEBUG] _ioc_access() : ... waiting on IOC_STATUS register ...\n");
-_tty_release_lock( 0 );
-#endif
-
-        }
-        // analyse status
-        error = ( (status == BLOCK_DEVICE_READ_ERROR) ||
-                  (status == BLOCK_DEVICE_WRITE_ERROR) );
-
-        // release lock
-        _release_lock(&_ioc_lock);      
-    }
-    else                           // in USER or KERNEL mode, we deschedule the task.
-                                   // When the task is rescheduled by the ISR, we reset 
-                                   // the _ioc_status variable, and release the lock
-    {
-        // We need a critical section, because we must reset the RUN bit
-		// before to launch the transfer, and we want to avoid to be descheduled
-		// between these two operations. 
-
-        // Enter critical section
-        _it_disable(); 
-        
-        // set _ioc_gtid and reset runnable 
-        unsigned int ltid = _get_proc_task_id();
-        unsigned int pid = _get_procid();
-        _ioc_gtid = (pid<<16) + ltid;
-        _set_task_slot( pid, ltid, CTX_RUN_ID, 0 );  
-        
-        // Launch transfert
-        if (to_mem == 0) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;
-        else             ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;
-
-        // deschedule task
-        _ctx_switch();                      
-
-        // analyse status
-        error = ( (_ioc_status == BLOCK_DEVICE_READ_ERROR) ||
-                  (_ioc_status == BLOCK_DEVICE_WRITE_ERROR) );
-
-        // reset _ioc_status and release lock
-        _ioc_status = BLOCK_DEVICE_IDLE; 
-        _release_lock(&_ioc_lock);      
-    }
-
-#if GIET_DEBUG_IOC_DRIVER
-_tty_get_lock( 0 );
-_puts("\n[IOC DEBUG] _ioc_access completed at cycle ");
-_putd( _get_proctime() );
-_puts(" for processor ");
-_putd( _get_procid() );
-_puts(" : error = ");
-_putd( (unsigned int)error );
-_puts("\n");
-_tty_release_lock( 0 );
+    if ( GIET_USE_IOMMU ) buf_paddr = (paddr_t) buf_xaddr;
+
+#if   USE_BDV
+    if (to_mem) error = _bdv_read (mode, lba, buf_paddr, count);
+    else        error = _bdv_write(mode, lba, buf_paddr, count);
+#elif USE_SPI
+    if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
+    else        error = _sdc_write(mode, lba, buf_paddr, count);
+#elif USE_HBA
+    if (to_mem) error = _hba_read (mode, lba, buf_paddr, count);
+    else        error = _hba_write(mode, lba, buf_paddr, count);
 #endif
 
@@ -392,16 +299,13 @@
 // Return 0 for success.
 ///////////////////////////////////////////////////////////////////////////////
-unsigned int _ioc_init()
-{
-    volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ;
-    
-    if ( ioc_address[BLOCK_DEVICE_BLOCK_SIZE] != 512 )
-    {
-        _puts("\n[GIET ERROR] in _ioc_init() : block size must be 512 bytes\n");
-        _exit();
-    }
-
-    ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
-    return 0;
+unsigned int _ioc_init( unsigned int channel )
+{
+#if   USE_BDV
+    return _bdv_init( channel );
+#elif USE_SPI
+    return _sdc_init( channel );
+#elif USE_HBA
+    return _hba_init( channel );
+#endif
 }
 
@@ -457,18 +361,11 @@
                               unsigned int* status )
 {
-    if ( channel != 0 )
-    {
-        _tty_get_lock( 0 );
-        _puts("\n[GIET ERROR] in _ioc_get_status : illegal channel\n");
-        _tty_release_lock( 0 );
-
-        return 1;
-    }
-
-    // get IOC base address
-    volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base;
-    *status = ioc_address[BLOCK_DEVICE_STATUS];
-
-    return 0;
+#if   USE_BDV
+    return _bdv_get_status(channel, status);
+#elif USE_SPI
+    return _sdc_get_status(channel, status);
+#elif USE_HBA
+    return _hba_get_status(channel, status);
+#endif
 }
 
@@ -479,8 +376,11 @@
 unsigned int _ioc_get_block_size() 
 {
-    // get IOC base address
-    volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base;
-    
-    return  ioc_address[BLOCK_DEVICE_BLOCK_SIZE];
+#if   USE_BDV
+    return _bdv_get_block_size();
+#elif USE_SPI
+    return _sdc_get_block_size();
+#elif USE_HBA
+    return _hba_get_block_size();
+#endif
 }
 
