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

Last change on this file since 690 was 670, checked in by alain, 3 years ago

1) Introduce up to 4 command lines arguments in the KSH "load" command.
These arguments are transfered to the user process through the
argc/argv mechanism, using the user space "args" vseg.

2) Introduce the named and anonymous "pipes", for inter-process communication
through the pipe() and mkfifo() syscalls.

3) Introduce the "chat" application to validate the two above mechanisms.

4) Improve printk() and assert() fonctions in printk.c.

File size: 10.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] %s / a1 %x / a2 %x / a3 %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_ACTIVE_WINDOW:
206        {
207            uint32_t  wid    = arg1;
208            uint32_t  active = arg2;
209
210            // call relevant kernel function
211            error = dev_fbf_active_window( wid , active );
212               
213            if( error )
214            {
215
216#if DEBUG_SYSCALLS_ERROR
217printk("\n[ERROR] in %s : cannot %s / thread[%x,%x]\n",
218__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
219#endif
220                this->errno = EINVAL;
221            }
222            break;
223        }
224        ///////////////////////
225        case FBF_DELETE_WINDOW:
226        {
227            uint32_t  wid = arg1;
228
229            // call relevant kernel function
230            error = dev_fbf_delete_window( wid );
231               
232            if( error )
233            {
234
235#if DEBUG_SYSCALLS_ERROR
236printk("\n[ERROR] in %s : cannot %s / thread[%x,%x]\n",
237__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
238#endif
239                this->errno = EINVAL;
240            }
241            break;
242        }
243        ////////////////////////
244        case FBF_REFRESH_WINDOW:
245        {
246            uint32_t  wid        = arg1;
247            uint32_t  line_first = arg2;
248            uint32_t  line_last  = arg3;
249
250            // call relevant kernel function
251            error = dev_fbf_refresh_window( wid,
252                                            line_first,
253                                            line_last );
254               
255            if( error )
256            {
257
258#if DEBUG_SYSCALLS_ERROR
259printk("\n[ERROR] in %s : cannot %s / thread[%x,%x]\n",
260__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
261#endif
262                this->errno = EINVAL;
263            }
264            break;
265        }
266        /////////////////////
267        case FBF_MOVE_WINDOW:
268        {
269            uint32_t  wid      = arg1; 
270            uint32_t  l_zero   = arg2;
271            uint32_t  p_zero   = arg3;
272
273            // call relevant kernel function to move data
274            error = dev_fbf_move_window( wid, l_zero, p_zero ); 
275
276            if( error )
277            {
278
279#if DEBUG_SYSCALLS_ERROR
280printk("\n[ERROR] in %s : cannot %s / thread[%x,%x]\n",
281__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
282#endif
283                this->errno = EINVAL;
284            }
285            break;
286        }
287        ///////////////////////
288        case FBF_RESIZE_WINDOW:
289        {
290            uint32_t  wid      = arg1; 
291            uint32_t  width    = arg2;
292            uint32_t  height   = arg3;
293
294            // call relevant kernel function to move data
295            error = dev_fbf_resize_window( wid , width , height ); 
296
297            if( error )
298            {
299
300#if DEBUG_SYSCALLS_ERROR
301printk("\n[ERROR] in %s : cannot %s / thread[%x,%x]\n",
302__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
303#endif
304                this->errno = EINVAL;
305            }
306            break;
307        }
308        //////////////////////
309        case FBF_FRONT_WINDOW:
310        {
311            uint32_t  wid = arg1;
312
313            // call relevant kernel function
314            error = dev_fbf_front_window( wid );
315               
316            if( error )
317            {
318
319#if DEBUG_SYSCALLS_ERROR
320printk("\n[ERROR] in %s : cannot %s / thread[%x,%x]\n",
321__FUNCTION__ , dev_fbf_cmd_str(operation), process->pid, this->trdid );
322#endif
323                this->errno = EINVAL;
324            }
325            break;
326        }
327        ///////
328            default:  // undefined operation                       
329        {
330
331#if DEBUG_SYSCALLS_ERROR
332printk("\n[ERROR] in %s : undefined operation type %d / thread %x in process %x / cycle %d\n",
333__FUNCTION__ , operation, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
334#endif
335            this->errno = EINVAL;
336            error = -1;
337        }
338        break;
339        }  // end switch on operation
340
341    hal_fence();
342
343#if (DEBUG_SYS_FBF || CONFIG_INSTRUMENTATION_SYSCALLS)
344uint64_t     tm_end = hal_get_cycles();
345#endif
346
347#if DEBUG_SYS_FBF
348if( DEBUG_SYS_FBF < tm_end )
349printk("\n[%s] thread[%x,%x] exit for %s / cycle %d\n",
350__FUNCTION__, process->pid, this->trdid, dev_fbf_cmd_str( operation ), (uint32_t)tm_end );
351#endif
352
353#if CONFIG_INSTRUMENTATION_SYSCALLS
354hal_atomic_add( &syscalls_cumul_cost[SYS_FBF] , tm_end - tm_start );
355hal_atomic_add( &syscalls_occurences[SYS_FBF] , 1 );
356#endif
357
358    return error;
359
360}  // end sys_fbf()
Note: See TracBrowser for help on using the repository browser.