Index: trunk/kernel/syscalls/sys_fbf.c
===================================================================
--- trunk/kernel/syscalls/sys_fbf.c	(revision 647)
+++ trunk/kernel/syscalls/sys_fbf.c	(revision 657)
@@ -2,5 +2,5 @@
  * sys_fbf.c - Acces the frame buffer peripheral.
  * 
- * Authors     Alain Greiner (2016,2017,2018,2019)
+ * Authors     Alain Greiner (2016,2017,2018,2019,2020)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -33,24 +33,28 @@
 #include <syscalls.h>
 
-//////////////////////////////////
-int sys_fbf( uint32_t   operation,
-             void     * arg0,           
-             void     * arg1,
-             void     * arg2 )
+////////////////////////
+int sys_fbf( reg_t arg0,
+             reg_t arg1,
+             reg_t arg2,
+             reg_t arg3 )
 {
 	vseg_t         * vseg;        // for vaddr check
     error_t          error;
 
+#if (DEBUG_SYS_FBF || CONFIG_INSTRUMENTATION_SYSCALLS)
+uint64_t     tm_start = hal_get_cycles();
+#endif
+
     thread_t       * this    = CURRENT_THREAD;
     process_t      * process = this->process;
 
-#if (DEBUG_SYS_FBF || CONFIG_INSTRUMENTATION_SYSCALLS)
-uint64_t     tm_start = hal_get_cycles();
-#endif
+    // for some operations, the MSB of arg0 can contain the wid 
+    uint32_t operation = arg0 & 0xFFFF;
 
 #if DEBUG_SYS_FBF
 if( DEBUG_SYS_FBF < tm_start )
-printk("\n[%s] thread[%x,%x] enter for %s / cycle %d\n",
-__FUNCTION__, process->pid, this->trdid, dev_fbf_cmd_str( operation ), (uint32_t)tm_start );
+printk("\n[%s] thread[%x,%x] enter for %s / arg1 %x / arg2 %x / arg3 %x / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, dev_fbf_cmd_str( operation ),
+arg1, arg2, arg3, (uint32_t)tm_start );
 #endif
 
@@ -65,18 +69,5 @@
             uint32_t type;
 
-            // check arg0 (width) in user vspace
-	        error = vmm_get_vseg( process , (intptr_t)arg0 , &vseg );
-	        if( error )
-            {
-
-#if DEBUG_SYSCALLS_ERROR
-printk("\n[ERROR] in %s : unmapped arg0 %x for %s / thread[%x,%x]\n",
-__FUNCTION__ , arg0, dev_fbf_cmd_str(operation), process->pid, this->trdid );
-#endif
-                this->errno = EINVAL;
-                return -1;
-            }
-
-            // check arg1 (height) in user vspace
+            // check "width" in user vspace
 	        error = vmm_get_vseg( process , (intptr_t)arg1 , &vseg );
 	        if( error )
@@ -88,9 +79,8 @@
 #endif
                 this->errno = EINVAL;
-                return -1;
-            }
-
-            // check arg2 (type) in user vspace
-	        error = vmm_get_vseg( process , (intptr_t)arg2 , &vseg );
+            }
+
+            // check "height" in user vspace
+	        error |= vmm_get_vseg( process , (intptr_t)arg2 , &vseg );
 	        if( error )
             {
@@ -101,5 +91,16 @@
 #endif
                 this->errno = EINVAL;
-                return -1;
+            }
+
+            // check "type" in user vspace
+	        error |= vmm_get_vseg( process , (intptr_t)arg3 , &vseg );
+	        if( error )
+            {
+
+#if DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s : unmapped arg3 %x for %s / thread[%x,%x]\n",
+__FUNCTION__ , arg3, dev_fbf_cmd_str(operation), process->pid, this->trdid );
+#endif
+                this->errno = EINVAL;
             }
 
@@ -107,35 +108,149 @@
             dev_fbf_get_config( &width , &height , &type );
 
-            // transfer to user space
-            hal_copy_to_uspace( arg0 , XPTR( local_cxy , &width )  , sizeof(uint32_t) );
-            hal_copy_to_uspace( arg1 , XPTR( local_cxy , &height ) , sizeof(uint32_t) );
-            hal_copy_to_uspace( arg2 , XPTR( local_cxy , &type )   , sizeof(uint32_t) );
-        
-            break;
-        }
-        //////////////
-        case FBF_READ:
-        case FBF_WRITE:
-        {
-            // check arg0 (buffer) in user space
-	        error = vmm_get_vseg( process , (intptr_t)arg0 , &vseg );
-	        if( error )
-            {
-
-#if DEBUG_SYSCALLS_ERROR
-printk("\n[ERROR] in %s : unmapped arg0 %x for %s / thread[%x,%x]\n",
-__FUNCTION__ , arg0, dev_fbf_cmd_str(operation), process->pid, this->trdid );
-#endif
-                this->errno = EINVAL;
-                return -1;
-            }
-
-            // get length and offset values
-
-            uint32_t length = (uint32_t)(intptr_t)arg1;
-            uint32_t offset = (uint32_t)(intptr_t)arg2;
+            // transfer to user space if no error
+            if( error == 0 )
+            {
+                hal_copy_to_uspace( (void*)arg1, XPTR(local_cxy , &width ), sizeof(uint32_t) );
+                hal_copy_to_uspace( (void*)arg2, XPTR(local_cxy , &height), sizeof(uint32_t) );
+                hal_copy_to_uspace( (void*)arg3, XPTR(local_cxy , &type  ), sizeof(uint32_t) );
+            }
+            break;
+        }
+        /////////////////////
+        case FBF_DIRECT_READ:
+        case FBF_DIRECT_WRITE:
+        {
+            void    * buffer   = (void *)arg1;
+            uint32_t  npixels  = arg2;
+            uint32_t  offset   = arg3;
+            bool_t    is_write = (operation == FBF_DIRECT_WRITE);
+            
+            // check buffer in user space
+	        error = vmm_get_vseg( process , (intptr_t)buffer , &vseg );
+	        if( error )
+            {
+
+#if DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s : unmapped buffer %x for %s / thread[%x,%x]\n",
+__FUNCTION__ , buffer, dev_fbf_cmd_str(operation), process->pid, this->trdid );
+#endif
+                this->errno = EINVAL;
+            }
+            else
+            {
+                // call relevant kernel function
+                error |= dev_fbf_move_data( is_write, buffer, npixels, offset );           
+
+                if( error )
+                {
+
+#if DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s : cannot move data for %s / buffer %x / thread[%x,%x]\n",
+__FUNCTION__ , dev_fbf_cmd_str(operation), buffer, process->pid, this->trdid );
+#endif
+                    this->errno = EINVAL;
+                }
+            }
+            break;
+        }
+        ///////////////////////
+        case FBF_CREATE_WINDOW:
+        {
+            uint32_t   l_zero  = arg1 >> 16;
+            uint32_t   p_zero  = arg1 & 0xFFFF;
+            uint32_t   nlines  = arg2 >> 16;
+            uint32_t   npixels = arg2 & 0xFFFF;
+
+            // check buffer in user space
+	        error = vmm_get_vseg( process , (intptr_t)arg3 , &vseg );
+	        if( error )
+            {
+
+#if DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s : unmapped user buffer %x for %s / thread[%x,%x]\n",
+__FUNCTION__ , (intptr_t)arg3, dev_fbf_cmd_str(operation), process->pid, this->trdid );
+#endif
+                this->errno = EINVAL;
+            }
+            else
+            {
+                // allocated buffer base address
+                intptr_t  user_buffer;
+     
+                // call relevant kernel function
+                error = dev_fbf_create_window( nlines,
+                                               npixels,
+                                               l_zero,
+                                               p_zero,
+                                               &user_buffer );
+                if( error == -1 )
+                {
+
+#if DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s : cannot create window for %s / thread[%x,%x]\n",
+__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
+#endif
+                    this->errno = EINVAL;
+                }
+
+                // copy vseg base address to user space buffer
+                hal_copy_to_uspace( (void *)arg3,
+                                    XPTR( local_cxy , &user_buffer ),
+                                    sizeof(intptr_t) );
+                hal_fence();
+            }
+            break;
+        }
+        ///////////////////////
+        case FBF_DELETE_WINDOW:
+        {
+            uint32_t  wid = arg1;
+
+            // call relevant kernel function
+            error = dev_fbf_delete_window( wid );
+                
+            if( error )
+            {
+
+#if DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s : cannot delete window for %s / thread[%x,%x]\n",
+__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
+#endif
+                this->errno = EINVAL;
+            }
+            break;
+        }
+        ////////////////////////
+        case FBF_REFRESH_WINDOW:
+        {
+            uint32_t  wid        = arg1;
+            uint32_t  line_first = arg2;
+            uint32_t  line_last  = arg3;
+
+            // call relevant kernel function
+            error = dev_fbf_refresh_window( wid,
+                                            line_first,
+                                            line_last );
+                
+            if( error )
+            {
+
+#if DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s : cannot refresh window for %s / thread[%x,%x]\n",
+__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
+#endif
+                this->errno = EINVAL;
+            }
+            break;
+        }
+        /////////////////////
+        case FBF_MOVE_WINDOW:
+        {
+            uint32_t  wid      = arg1; 
+            uint32_t  l_zero   = arg2;
+            uint32_t  p_zero   = arg3;
 
             // call relevant kernel function to move data
-            error = dev_fbf_move_data( operation , arg0 , length , offset ); 
+            error = dev_fbf_move_window( wid, l_zero, p_zero ); 
 
             if( error )
@@ -143,11 +258,30 @@
 
 #if DEBUG_SYSCALLS_ERROR
-printk("\n[ERROR] in %s : cannot move data for %s / buffer %x / thread[%x,%x]\n",
-__FUNCTION__ , dev_fbf_cmd_str(operation), arg0, process->pid, this->trdid );
-#endif
-                this->errno = EINVAL;
-                return -1;
-            }
-          
+printk("\n[ERROR] in %s : cannot move window / thread[%x,%x]\n",
+__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
+#endif
+                this->errno = EINVAL;
+            }
+            break;
+        }
+        ///////////////////////
+        case FBF_RESIZE_WINDOW:
+        {
+            uint32_t  wid      = arg1; 
+            uint32_t  width    = arg2;
+            uint32_t  height   = arg3;
+
+            // call relevant kernel function to move data
+            error = dev_fbf_resize_window( wid , width , height ); 
+
+            if( error )
+            {
+
+#if DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s : cannot move window / thread[%x,%x]\n",
+__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
+#endif
+                this->errno = EINVAL;
+            }
             break;
         }
@@ -161,6 +295,7 @@
 #endif
             this->errno = EINVAL;
-            return -1;
-        }
+            error = -1;
+        }
+        break;
 	}  // end switch on operation
 
@@ -173,7 +308,6 @@
 #if DEBUG_SYS_FBF
 if( DEBUG_SYS_FBF < tm_end )
-printk("\n[%s] thread[%x,%x] exit for %s / cost = %d / cycle %d\n",
-__FUNCTION__, process->pid, this->trdid, dev_fbf_cmd_str( operation ),
-(uint32_t)(tm_end - tm_start), (uint32_t)tm_end );
+printk("\n[%s] thread[%x,%x] exit for %s / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, dev_fbf_cmd_str( operation ), (uint32_t)tm_end );
 #endif
 
@@ -183,5 +317,5 @@
 #endif
 
-    return 0;
+    return error;
 
 }  // end sys_fbf()
