Index: soft/giet_vm/giet_drivers/ioc_driver.c
===================================================================
--- soft/giet_vm/giet_drivers/ioc_driver.c	(revision 350)
+++ soft/giet_vm/giet_drivers/ioc_driver.c	(revision 413)
@@ -6,82 +6,15 @@
 // Copyright (c) UPMC-LIP6
 ///////////////////////////////////////////////////////////////////////////////////
-// The ioc_driver.c and ioc_driver.h files are part ot the GIET-VM kernel.
+// Implementation note:
 //
-// This abstact driver define a generic API, supporting various physical
-// block device controlers, including:
-// - vci_block_device : single channel)                    => bdv_driver
-// - vci_ahci         : multi channels                     => hba_driver
-// - sd_card          : single channel                     => sdc_driver
-// - ramdisk (single channel meory mapped virtual disk)    => rdk_driver
+// 1) In order to share the code, the two _ioc_read() and _ioc_write() functions
+// call the same _ioc_access() function.
 //
-// It can exist only one block-device type in the architecture, that must be
-// defined by one of the following configuration variables in hard_config.h file:
-// USE_IOC_BDV, USE_IOC_SDC, USE_IOC_HBA, USE_IOC_RDK.
-//
-// Any physical driver xxx must provide the following API:
-// - _xxx_init()
-// - _xxx_read()
-// - _xxx_write()
-// - _xxx_get_status()
-// - _xxx_get_block_size()
-// The "channel" parameter is no transmited to single channel devices.
-//
-// The _ioc_read() and _ioc_write() functions are always blocking for
-// the calling user program.
-//
-// These functions compute the physical address of the memory buffer before 
-// calling the proper physical device. They can be called in 3 modes:
-//
-// - In BOOT mode, these functions use the buffer virtual address
-//   as a physical address if the MMU is not activated.
-//   They make a V2P translation if the MMU is activated.
-//   This mode is used to load the map.bin file (before memory activation),
-//   or to load the various .elf files (after MMU activation).
-//
-// - In KERNEL mode, these functions make a V2P translation to
-//   compute the buffer physical address.
-//   There is no checking of user access right to the memory buffer.  
-//   This mode must be used for an "open" system call.
-//
-// - In USER mode, these functions make a V2P translation to
-//   compute the buffer physical address. 
-//   The user access right to the memory buffer are checked.  
-//   This mode must be used for a "read" or "write" system call.
-//
-// The IOMMU can be activated or not:
-// 
-// 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to 
-// the IOC peripheral, in the I/O virtual space, and the user buffer is
-// dynamically remapped in the IOMMU page table. The corresponding entry 
-// in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable.
-// The number of pages to be unmapped is stored in the _ioc_npages variable.
-// The number of PT2 entries is dynamically computed and stored in the
-// kernel _ioc_iommu_npages variable. It cannot be larger than 512.
+// 2) The IOMMU is not supported yet, but the method is the following:
+// A fixed size 2 Mbytes vseg is allocated to the IOC peripheral, in the I/O 
+// virtual space, and the user buffer is dynamically remapped to one single
+// big page in the IOMMU page table.
 // The user buffer is unmapped by the _ioc_completed() function when 
 // the transfer is completed.
-//
-// 2/ If the IOMMU is not used, we check that  the user buffer is mapped to a
-// contiguous physical buffer (this is generally true because the user space
-// page tables are statically constructed to use contiguous physical memory).
-//
-// Finally, the memory buffer must fulfill the following conditions:
-// - The buffer must be word aligned, 
-// - The buffer must be mapped in user space for an user access, 
-// - The buffer must be writable in case of (to_mem) access,
-// - The total number of physical pages occupied by the user buffer cannot
-//   be larger than 512 pages if the IOMMU is activated,
-// - All physical pages occupied by the user buffer must be contiguous
-//   if the IOMMU is not activated.
-// An error code is returned if these conditions are not verified.
-//
-// The SEG_IOC_BASE virtual base address must be defined in hard_config.h,
-// as it is used by the BDV, HBA and SPI drivers.
-//
-// If the RAMDISK is used, an extra memory segment with virtual base address
-// SEG_RDK_BASE, used by RDK driver, must be defined in hard_config.h.
-///////////////////////////////////////////////////////////////////////////////////
-// Implementation note:
-// In order to share the code, the two _ioc_read() and _ioc_write() functions
-// call the same _ioc_access() function.
 ///////////////////////////////////////////////////////////////////////////////////
 
@@ -166,5 +99,5 @@
 unsigned int y       = cid & ((1<<Y_WIDTH) - 1);
 
-_printf("\n[IOC DEBUG] Processor[%d,%d,%d] enters _ioc_access() at cycle %d\n"
+_printf("\n[IOC DEBUG] _ioc_access() : P[%d,%d,%d] enters at cycle %d\n"
         " - channel  = %d\n"
         " - mode     = %d\n"
@@ -177,18 +110,12 @@
     unsigned int error;            // return value
     unsigned int pt_vbase;         // page table vbase address
-    unsigned int vpn_min;          // first virtuel page index covering buffer
-    unsigned int vpn_max;          // last virtual page index covering buffer
-    unsigned int vpn;              // current virtual page index
-    unsigned int ppn;              // physical page number
-    unsigned int flags;            // page protection flags
-    unsigned int ix2;              // page index in IOMMU PT1 page table
-    unsigned int ppn_first = 0;    // first physical page number for user buffer
-    unsigned int buf_xaddr = 0;    // user buffer virtual address in IO space (if IOMMU)
-    paddr_t      buf_paddr = 0;    // user buffer physical address (if no IOMMU),
+    unsigned int ppn;              // user buffer first page PPN
+    unsigned int flags;            // user buffer protection flags
+    paddr_t      buf_paddr;        // user buffer physical address (if no IOMMU),
 
     // check buffer alignment
     if ((unsigned int) buf_vaddr & 0x3)
     {
-        _printf("\n[GIET ERROR] in _ioc_access() : buffer not word aligned\n");
+        _printf("\n[IOC ERROR] in _ioc_access() : buffer not word aligned\n");
         _exit(); 
     }
@@ -197,5 +124,5 @@
     if ( (USE_IOC_HBA == 0) && (channel > 0) )
     {
-        _printf("\n[GIET ERROR] in _ioc_access() : channel must be 0 when HBA not used\n");
+        _printf("\n[IOC ERROR] in _ioc_access() : channel must be 0 when HBA not used\n");
         _exit(); 
     }
@@ -212,83 +139,40 @@
         // get page table virtual address
         pt_vbase = _get_context_slot(CTX_PTAB_ID);
-        vpn_min  = buf_vaddr >> 12;
-        vpn_max  = (buf_vaddr + length - 1) >> 12;
-
-        // loop on all virtual pages covering the user buffer
-        for (vpn = vpn_min, ix2 = 0 ; vpn <= vpn_max ; vpn++, ix2++ ) 
+
+        // get user buffer first page ppn and flags
+        unsigned int ko = _v2p_translate( (page_table_t*)pt_vbase,
+                                           buf_vaddr >> 12,
+                                           &ppn,
+                                           &flags );
+        // check access rights
+        if ( ko )
         {
-            // get ppn and flags for each vpn
-            unsigned int ko = _v2p_translate( (page_table_t*)pt_vbase,
-                                              vpn,
-                                              &ppn,
-                                              &flags);
-            // check access rights
-            if ( ko )
-            {
-                _printf("\n[GIET ERROR] in _ioc_access() : buffer unmapped\n");
-                return 1; 
-            }
-
-            if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
-            {
-                _printf("\n[GIET ERROR] in _ioc_access() : buffer not user accessible\n");
-                return 1; 
-            }
-
-            if ( ((flags & PTE_W) == 0 ) && to_mem )
-            {
-                _printf("\n[GIET ERROR] in _ioc_access() : buffer not writable\n");
-                return 1; 
-            }
-
-            // save first ppn value
-            if (ix2 == 0) ppn_first = ppn;
-
-#if GIET_USE_IOMMU 
- 
-            // check buffer length < 2 Mbytes
-            if (ix2 > 511) // check buffer length < 2 Mbytes
-            {
-                _printf("\n[GIET ERROR] in _ioc_access() : user buffer > 2 Mbytes\n");
-                return 1; 
-            }
-            // map the physical page in IOMMU page table
-            _iommu_add_pte2( _ioc_iommu_ix1,    // PT1 index
-                             ix2,               // PT2 index
-                             ppn,               // Physical page number    
-                             flags );           // Protection flags
-
-            // compute user buffer virtual adress in IO space
-            buf_xaddr = (_ioc_iommu_ix1) << 21 | (buf_vaddr & 0xFFF);
-
-#else
-
-            // check that physical pages are contiguous
-            if ((ppn - ppn_first) != ix2) 
-            {
-                _printf("[GIET ERROR] in _ioc_access() : split physical buffer\n");
-                return 1; 
-            }
-
-            // compute user buffer physical adress
-            buf_paddr = (((paddr_t)ppn_first) << 12) | (buf_vaddr & 0xFFF);
-#endif            
-
-        } // end for vpn
-    }
-
-#if GIET_USE_IOMMU 
-
-    // register the number of pages to be unmapped in IOMMU
-    _ioc_iommu_npages = (vpn_max - vpn_min) + 1;
-
-#endif
+            _printf("\n[IOC ERROR] in _ioc_access() : buffer unmapped\n");
+            _exit(); 
+        }
+
+        if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
+        {
+            _printf("\n[IOC ERROR] in _ioc_access() : buffer not user accessible\n");
+            _exit(); 
+        }
+
+        if ( ((flags & PTE_W) == 0 ) && to_mem )
+        {
+            _printf("\n[IOC ERROR] in _ioc_access() : buffer not writable\n");
+            _exit(); 
+        }
+
+        buf_paddr = (((paddr_t)ppn) << 12) | (buf_vaddr & 0xFFF);
+    }
+
+    // cache coherence for both L1 & L2 caches
 
     if ( to_mem ) // memory write : invalidate data caches 
     {
-        // L1 cache
-        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate((void *) buf_vaddr, length);
-
-        // L2 cache (only if IOB used)
+        // L1 cache (only if L1 cache coherence not guaranteed by hardware)
+        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( buf_vaddr, length );
+
+        // L2 cache (only if we use an IO-Bridge component in architecture))
         if ( USE_IOB ) _mmc_inval( buf_paddr, length );
     }
@@ -297,15 +181,11 @@
         // L1 cache : nothing to do for L1 write-through
 
-        // L2 cache (only if IOB used)
+        // L2 cache (only if we use an IO-Bridge component in architecture))
         if ( USE_IOB ) _mmc_sync( buf_paddr, length );
     }
 
-    if ( GIET_USE_IOMMU ) buf_paddr = (paddr_t) buf_xaddr;
-
-    ///////////////////////////////////////////
     // select the proper physical device 
-    ///////////////////////////////////////////
-
-#if       ( USE_IOC_BDV )
+
+#if   ( USE_IOC_BDV )
         if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count);
         else        error = _bdv_write( mode, lba, buf_paddr, count);
@@ -324,8 +204,5 @@
 } // end _ioc_access()
 
-///////////////////////////////////////////////////////////////////////////////
-// This function cheks block size, and desactivates the IOC interrupts.
-// Return 0 for success.
-///////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////
 unsigned int _ioc_init( unsigned int channel )
 {
@@ -351,12 +228,5 @@
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Transfer data from the block device to a memory buffer. 
-// - mode     : BOOT_PA / BOOT_VA / KERNEL / USER 
-// - lba      : first block index on the block device
-// - buffer   : base address of the memory buffer (must be word aligned)
-// - count    : number of blocks to be transfered.
-// Returns 0 if success, > 0 if error.
-///////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////
 unsigned int _ioc_read( unsigned int channel,
                         unsigned int mode,  
@@ -373,12 +243,5 @@
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Transfer data from a memory buffer to the block device. 
-// - mode     : BOOT_PA / BOOT_VA / KERNEL / USER 
-// - lba      : first block index on the block device
-// - buffer   : base address of the memory buffer (must be word aligned)
-// - count    : number of blocks to be transfered.
-// Returns 0 if success, > 0 if error.
-///////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////
 unsigned int _ioc_write( unsigned int channel,
                          unsigned int mode,  
@@ -395,9 +258,5 @@
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// This function returns in the status variable, the transfert status, and
-// acknowledge the IRQ if the IOC controler is not busy.
-// Returns 0 if success, > 0 if error
-///////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////
 unsigned int _ioc_get_status( unsigned int  channel )
 {
@@ -427,7 +286,5 @@
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// This function returns the block_size with which the IOC has been configured.
-///////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////
 unsigned int _ioc_get_block_size() 
 {
