source: trunk/kernel/syscalls/sys_fbf.c @ 666

Last change on this file since 666 was 657, checked in by alain, 5 years ago

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

File size: 9.8 KB
Line 
1/*
2 * sys_fbf.c - Acces the frame buffer peripheral.
3 *
4 * Authors     Alain Greiner (2016,2017,2018,2019,2020)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_kernel_types.h>
25#include <hal_uspace.h>
26#include <hal_vmm.h>
27#include <shared_fbf.h>
28#include <dev_fbf.h>
29#include <errno.h>
30#include <thread.h>
31#include <printk.h>
32#include <vmm.h>
33#include <syscalls.h>
34
35////////////////////////
36int sys_fbf( reg_t arg0,
37             reg_t arg1,
38             reg_t arg2,
39             reg_t arg3 )
40{
41        vseg_t         * vseg;        // for vaddr check
42    error_t          error;
43
44#if (DEBUG_SYS_FBF || CONFIG_INSTRUMENTATION_SYSCALLS)
45uint64_t     tm_start = hal_get_cycles();
46#endif
47
48    thread_t       * this    = CURRENT_THREAD;
49    process_t      * process = this->process;
50
51    // for some operations, the MSB of arg0 can contain the wid
52    uint32_t operation = arg0 & 0xFFFF;
53
54#if DEBUG_SYS_FBF
55if( DEBUG_SYS_FBF < tm_start )
56printk("\n[%s] thread[%x,%x] enter for %s / arg1 %x / arg2 %x / arg3 %x / cycle %d\n",
57__FUNCTION__, process->pid, this->trdid, dev_fbf_cmd_str( operation ),
58arg1, arg2, arg3, (uint32_t)tm_start );
59#endif
60
61    // execute requested operation
62        switch( operation )
63        {
64        ////////////////////
65            case FBF_GET_CONFIG:
66        {
67            uint32_t width;
68            uint32_t height;
69            uint32_t type;
70
71            // check "width" in user vspace
72                error = vmm_get_vseg( process , (intptr_t)arg1 , &vseg );
73                if( error )
74            {
75
76#if DEBUG_SYSCALLS_ERROR
77printk("\n[ERROR] in %s : unmapped arg1 %x for %s / thread[%x,%x]\n",
78__FUNCTION__ , arg1, dev_fbf_cmd_str(operation), process->pid, this->trdid );
79#endif
80                this->errno = EINVAL;
81            }
82
83            // check "height" in user vspace
84                error |= vmm_get_vseg( process , (intptr_t)arg2 , &vseg );
85                if( error )
86            {
87
88#if DEBUG_SYSCALLS_ERROR
89printk("\n[ERROR] in %s : unmapped arg2 %x for %s / thread[%x,%x]\n",
90__FUNCTION__ , arg2, dev_fbf_cmd_str(operation), process->pid, this->trdid );
91#endif
92                this->errno = EINVAL;
93            }
94
95            // check "type" in user vspace
96                error |= vmm_get_vseg( process , (intptr_t)arg3 , &vseg );
97                if( error )
98            {
99
100#if DEBUG_SYSCALLS_ERROR
101printk("\n[ERROR] in %s : unmapped arg3 %x for %s / thread[%x,%x]\n",
102__FUNCTION__ , arg3, dev_fbf_cmd_str(operation), process->pid, this->trdid );
103#endif
104                this->errno = EINVAL;
105            }
106
107            // call relevant kernel function to get  config
108            dev_fbf_get_config( &width , &height , &type );
109
110            // transfer to user space if no error
111            if( error == 0 )
112            {
113                hal_copy_to_uspace( (void*)arg1, XPTR(local_cxy , &width ), sizeof(uint32_t) );
114                hal_copy_to_uspace( (void*)arg2, XPTR(local_cxy , &height), sizeof(uint32_t) );
115                hal_copy_to_uspace( (void*)arg3, XPTR(local_cxy , &type  ), sizeof(uint32_t) );
116            }
117            break;
118        }
119        /////////////////////
120        case FBF_DIRECT_READ:
121        case FBF_DIRECT_WRITE:
122        {
123            void    * buffer   = (void *)arg1;
124            uint32_t  npixels  = arg2;
125            uint32_t  offset   = arg3;
126            bool_t    is_write = (operation == FBF_DIRECT_WRITE);
127           
128            // check buffer in user space
129                error = vmm_get_vseg( process , (intptr_t)buffer , &vseg );
130                if( error )
131            {
132
133#if DEBUG_SYSCALLS_ERROR
134printk("\n[ERROR] in %s : unmapped buffer %x for %s / thread[%x,%x]\n",
135__FUNCTION__ , buffer, dev_fbf_cmd_str(operation), process->pid, this->trdid );
136#endif
137                this->errno = EINVAL;
138            }
139            else
140            {
141                // call relevant kernel function
142                error |= dev_fbf_move_data( is_write, buffer, npixels, offset );           
143
144                if( error )
145                {
146
147#if DEBUG_SYSCALLS_ERROR
148printk("\n[ERROR] in %s : cannot move data for %s / buffer %x / thread[%x,%x]\n",
149__FUNCTION__ , dev_fbf_cmd_str(operation), buffer, process->pid, this->trdid );
150#endif
151                    this->errno = EINVAL;
152                }
153            }
154            break;
155        }
156        ///////////////////////
157        case FBF_CREATE_WINDOW:
158        {
159            uint32_t   l_zero  = arg1 >> 16;
160            uint32_t   p_zero  = arg1 & 0xFFFF;
161            uint32_t   nlines  = arg2 >> 16;
162            uint32_t   npixels = arg2 & 0xFFFF;
163
164            // check buffer in user space
165                error = vmm_get_vseg( process , (intptr_t)arg3 , &vseg );
166                if( error )
167            {
168
169#if DEBUG_SYSCALLS_ERROR
170printk("\n[ERROR] in %s : unmapped user buffer %x for %s / thread[%x,%x]\n",
171__FUNCTION__ , (intptr_t)arg3, dev_fbf_cmd_str(operation), process->pid, this->trdid );
172#endif
173                this->errno = EINVAL;
174            }
175            else
176            {
177                // allocated buffer base address
178                intptr_t  user_buffer;
179     
180                // call relevant kernel function
181                error = dev_fbf_create_window( nlines,
182                                               npixels,
183                                               l_zero,
184                                               p_zero,
185                                               &user_buffer );
186                if( error == -1 )
187                {
188
189#if DEBUG_SYSCALLS_ERROR
190printk("\n[ERROR] in %s : cannot create window for %s / thread[%x,%x]\n",
191__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
192#endif
193                    this->errno = EINVAL;
194                }
195
196                // copy vseg base address to user space buffer
197                hal_copy_to_uspace( (void *)arg3,
198                                    XPTR( local_cxy , &user_buffer ),
199                                    sizeof(intptr_t) );
200                hal_fence();
201            }
202            break;
203        }
204        ///////////////////////
205        case FBF_DELETE_WINDOW:
206        {
207            uint32_t  wid = arg1;
208
209            // call relevant kernel function
210            error = dev_fbf_delete_window( wid );
211               
212            if( error )
213            {
214
215#if DEBUG_SYSCALLS_ERROR
216printk("\n[ERROR] in %s : cannot delete window for %s / thread[%x,%x]\n",
217__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
218#endif
219                this->errno = EINVAL;
220            }
221            break;
222        }
223        ////////////////////////
224        case FBF_REFRESH_WINDOW:
225        {
226            uint32_t  wid        = arg1;
227            uint32_t  line_first = arg2;
228            uint32_t  line_last  = arg3;
229
230            // call relevant kernel function
231            error = dev_fbf_refresh_window( wid,
232                                            line_first,
233                                            line_last );
234               
235            if( error )
236            {
237
238#if DEBUG_SYSCALLS_ERROR
239printk("\n[ERROR] in %s : cannot refresh window for %s / thread[%x,%x]\n",
240__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
241#endif
242                this->errno = EINVAL;
243            }
244            break;
245        }
246        /////////////////////
247        case FBF_MOVE_WINDOW:
248        {
249            uint32_t  wid      = arg1; 
250            uint32_t  l_zero   = arg2;
251            uint32_t  p_zero   = arg3;
252
253            // call relevant kernel function to move data
254            error = dev_fbf_move_window( wid, l_zero, p_zero ); 
255
256            if( error )
257            {
258
259#if DEBUG_SYSCALLS_ERROR
260printk("\n[ERROR] in %s : cannot move window / thread[%x,%x]\n",
261__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
262#endif
263                this->errno = EINVAL;
264            }
265            break;
266        }
267        ///////////////////////
268        case FBF_RESIZE_WINDOW:
269        {
270            uint32_t  wid      = arg1; 
271            uint32_t  width    = arg2;
272            uint32_t  height   = arg3;
273
274            // call relevant kernel function to move data
275            error = dev_fbf_resize_window( wid , width , height ); 
276
277            if( error )
278            {
279
280#if DEBUG_SYSCALLS_ERROR
281printk("\n[ERROR] in %s : cannot move window / thread[%x,%x]\n",
282__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
283#endif
284                this->errno = EINVAL;
285            }
286            break;
287        }
288        ///////
289            default:  // undefined operation                       
290        {
291
292#if DEBUG_SYSCALLS_ERROR
293printk("\n[ERROR] in %s : undefined operation type %d / thread %x in process %x / cycle %d\n",
294__FUNCTION__ , operation, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
295#endif
296            this->errno = EINVAL;
297            error = -1;
298        }
299        break;
300        }  // end switch on operation
301
302    hal_fence();
303
304#if (DEBUG_SYS_FBF || CONFIG_INSTRUMENTATION_SYSCALLS)
305uint64_t     tm_end = hal_get_cycles();
306#endif
307
308#if DEBUG_SYS_FBF
309if( DEBUG_SYS_FBF < tm_end )
310printk("\n[%s] thread[%x,%x] exit for %s / cycle %d\n",
311__FUNCTION__, process->pid, this->trdid, dev_fbf_cmd_str( operation ), (uint32_t)tm_end );
312#endif
313
314#if CONFIG_INSTRUMENTATION_SYSCALLS
315hal_atomic_add( &syscalls_cumul_cost[SYS_FBF] , tm_end - tm_start );
316hal_atomic_add( &syscalls_occurences[SYS_FBF] , 1 );
317#endif
318
319    return error;
320
321}  // end sys_fbf()
Note: See TracBrowser for help on using the repository browser.