source: trunk/kernel/devices/dev_fbf.c @ 659

Last change on this file since 659 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: 35.5 KB
Line 
1/*
2 * dev_fbf.c - FBF (Frame Buffer) generic device API implementation.
3 *
4 * Author  Alain Greiner    (2016,2017,2018,2019,2020)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MK
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-kernel; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <kernel_config.h>
25#include <hal_kernel_types.h>
26#include <hal_gpt.h>
27#include <hal_drivers.h>
28#include <hal_irqmask.h>
29#include <hal_macros.h>
30#include <hal_uspace.h>
31#include <hal_vmm.h>
32#include <thread.h>
33#include <printk.h>
34#include <string.h>
35#include <memcpy.h>
36#include <chdev.h>
37#include <dev_fbf.h>
38
39/////////////////////////////////////////////////////////////////////////////////////////
40// Extern global variables
41/////////////////////////////////////////////////////////////////////////////////////////
42
43extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
44
45///////////////////////////////////////////
46char * dev_fbf_cmd_str( uint32_t cmd_type )
47{
48    if     ( cmd_type == FBF_GET_CONFIG     )  return "GET_CONFIG";
49    else if( cmd_type == FBF_CREATE_WINDOW  )  return "CREATE_WINDOW";
50    else if( cmd_type == FBF_DELETE_WINDOW  )  return "DELETE_WINDOW";
51    else if( cmd_type == FBF_MOVE_WINDOW    )  return "MOVE_WINDOW";
52    else if( cmd_type == FBF_REFRESH_WINDOW )  return "REFRESH_WINDOW";
53    else if( cmd_type == FBF_DIRECT_WRITE   )  return "DIRECT_WRITE";
54    else if( cmd_type == FBF_DIRECT_READ    )  return "DIRECT_READ";
55    else                                       return "undefined";
56}
57
58////////////////////////////////////
59void dev_fbf_init( chdev_t  * fbf )
60{
61    uint32_t wid;
62
63    // set chdev name
64    strcpy( fbf->name, "fbf" );
65
66    // initialize lock protecting the windows
67    remote_rwlock_init( XPTR( local_cxy , &fbf->ext.fbf.windows_lock ),
68                        LOCK_FBF_WINDOWS ); 
69
70    // initialize root of windows xlist
71    xlist_root_init( XPTR( local_cxy , &fbf->ext.fbf.windows_root ) );
72
73    // initialize windows_tbl[] array
74    for( wid = 0 ; wid < CONFIG_FBF_WINDOWS_MAX_NR ; wid++ ) 
75    {
76        fbf->ext.fbf.windows_tbl[wid] = XPTR_NULL;
77    }
78
79    // initialize wid allocator bitmap
80    bitmap_init( fbf->ext.fbf.windows_bitmap , CONFIG_FBF_WINDOWS_MAX_NR );
81
82    // call driver init function to initialize the harware FBF
83    // and initialize the width, height, and subsampling FBF chdev fields
84    hal_drivers_fbf_init( fbf );
85
86}  // end dev_fbf_init()
87
88//////////////////////////////////////////
89void dev_fbf_get_config( uint32_t * width,
90                         uint32_t * height,
91                         uint32_t * type )
92{
93    // get extended pointer on FBF chdev descriptor
94    xptr_t  dev_xp = chdev_dir.fbf[0];
95
96assert( (dev_xp != XPTR_NULL) , "undefined FBF chdev descriptor" );
97
98    // get FBF chdev cluster and local pointer
99    cxy_t     dev_cxy = GET_CXY( dev_xp );
100    chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
101
102    // return values
103    *width  = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.width ) );
104    *height = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.height ) );
105    *type   = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.subsampling ) );
106
107}  // end dev_fbf_get_config()
108
109///////////////////////////////////////////////
110uint32_t dev_fbf_create_window( uint32_t   nlines,
111                                uint32_t   npixels,
112                                uint32_t   l_min,
113                                uint32_t   p_min,
114                                intptr_t * user_buffer )
115{
116    kmem_req_t     req;
117    fbf_window_t * window;      // window descriptor (created in local cluster)
118    vseg_t       * vseg;        // vseg descriptor (created in reference cluster)
119    intptr_t       vseg_base;   // vseg base address in user space 
120
121    // get local pointers on calling thread and process
122    thread_t  * this    = CURRENT_THREAD;
123    process_t * process = this->process;
124
125#if DEBUG_DEV_FBF
126uint32_t   cycle = (uint32_t)hal_get_cycles();
127if( DEBUG_DEV_FBF < cycle )
128printk("\n[%s] thread[%x,%x] enter : nlines %d / npixels %d / l_min %d / p_min %d / cycle %d\n",
129__FUNCTION__ , process->pid, this->trdid, nlines, npixels, l_min, p_min, cycle );
130#endif
131
132    // get cluster and pointers on FBF chdev
133    xptr_t      fbf_xp  = chdev_dir.fbf[0];
134    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
135    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
136
137// check fbf_xp definition
138assert( (fbf_xp != XPTR_NULL) , "undefined FBF chdev descriptor" );
139
140    // get FBF width and height
141    uint32_t fbf_width  = hal_remote_l32( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.width ) );
142    uint32_t fbf_height = hal_remote_l32( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.height ) );
143
144    // check new window size and coordinates
145    if( (((l_min + nlines) > fbf_height) || ((p_min + npixels) > fbf_width)) )
146    {
147        printk("\n[ERROR] in %s / thread[%x,%x]" 
148        "illegal new coordinates (%d,%d) for window (%d,%d) in fbf (%d,%d)\n",
149        process->pid, this->trdid, p_min, l_min, npixels, nlines, fbf_width, fbf_height );
150        return -1;
151    }
152
153    // build extended pointers on windows lock, root, and wid allocator
154    xptr_t windows_lock_xp   = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
155    xptr_t windows_root_xp   = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
156    xptr_t windows_bitmap_xp = XPTR( fbf_cxy ,  fbf_ptr->ext.fbf.windows_bitmap );
157 
158    // allocate memory for the window descriptor in local cluster
159    req.type   = KMEM_KCM;
160    req.order  = bits_log2( sizeof(fbf_window_t) );
161    req.flags  = AF_ZERO | AF_KERNEL;
162    window     = kmem_alloc( &req );
163
164    if( window == NULL )
165    {
166        printk("\n[ERROR] in %s / thread[%x,%x] cannot allocate window descriptor\n",
167        __FUNCTION__, process->pid, this->trdid );
168        return -1;
169    }
170
171#if (DEBUG_DEV_FBF & 1)
172cycle = (uint32_t)hal_get_cycles();
173if( DEBUG_DEV_FBF < cycle )
174printk("\n[%s] thread[%x,%x] created window descriptor %x / cycle %d\n",
175__FUNCTION__ , process->pid, this->trdid, window, cycle );
176#endif
177
178    // getpointers on reference process
179    xptr_t      ref_xp  = process->ref_xp;
180    process_t * ref_ptr = GET_PTR( ref_xp );
181    cxy_t       ref_cxy = GET_CXY( ref_xp );
182
183    // allocate a new vseg, and introduce it in the reference process VSL
184    if( ref_cxy == local_cxy )
185    {
186        vseg = vmm_create_vseg( process,            // owner process
187                                VSEG_TYPE_ANON,     // localised, public
188                                0,                  // base, unused for ANON
189                                nlines * npixels,   // size
190                                0,                  // file_offset, unused for ANON
191                                0,                  // file_size, unused for ANON
192                                XPTR_NULL,          // mapper_xp, unused for ANON
193                                local_cxy );        // mapping cluster
194    }
195    else
196    {
197        rpc_vmm_create_vseg_client( ref_cxy,
198                                    ref_ptr,
199                                    VSEG_TYPE_ANON,
200                                    0,                 // base, unused for ANON
201                                    nlines * npixels,  // size
202                                    0,                 // file_offset, unused for ANON
203                                    0,                 // file size, unused for ANON
204                                    XPTR_NULL,         // mapper_xp, unused for ANON
205                                    local_cxy,
206                                    &vseg );
207    } 
208       
209    if( vseg == NULL )
210    {
211        printk("\n[ERROR] in %s / thread[%x,%x] cannot create vseg in reference cluster\n",
212        __FUNCTION__, process->pid, this->trdid );
213        req.ptr = (void *)window;
214        kmem_free( &req );
215        return -1;
216    }
217
218    // get vseg base
219    vseg_base = (intptr_t)hal_remote_lpt( XPTR( ref_cxy , &vseg->min ) );
220
221#if (DEBUG_DEV_FBF & 1)
222cycle = (uint32_t)hal_get_cycles();
223if( DEBUG_DEV_FBF < cycle )
224printk("\n[%s] thread[%x,%x] allocated vseg / base %x / cycle %d\n",
225__FUNCTION__ , process->pid, this->trdid, vseg_base, cycle );
226#endif
227
228    // take the lock protecting windows in write mode
229    remote_rwlock_wr_acquire( windows_lock_xp );
230
231    // allocate a wid from allocator in FBF descriptor extension
232    uint32_t wid = bitmap_remote_alloc( windows_bitmap_xp , CONFIG_FBF_WINDOWS_MAX_NR );
233
234    if( wid == 0xFFFFFFFF )
235    {
236        printk("\n[ERROR] in %s / thread[%x,%x] cannot allocate buffer for window\n",
237        __FUNCTION__, process->pid, this->trdid );
238        req.ptr = (void *)window;
239        kmem_free( &req );
240        vmm_remove_vseg( process , vseg );
241        return -1;
242    }
243 
244    // initialize window descriptor
245    window->pid     = process->pid;
246    window->wid     = wid;
247    window->height  = nlines;
248    window->width   = npixels;
249    window->l_min   = l_min;
250    window->p_min   = p_min;
251    window->hidden  = false;
252    window->buffer  = (uint8_t *)vseg_base;
253
254    // register new window in xlist rooted in FBF extension
255    xlist_add_last( windows_root_xp , XPTR( local_cxy , &window->xlist ) );
256
257    // build extended pointer on relevant entry in windows_tbl[] array
258    xptr_t windows_tbl_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_tbl[wid] );
259
260    // register new window in windows_tbl[] stored in FBF extension
261    hal_remote_s64( windows_tbl_xp , XPTR( local_cxy , window ) );
262
263    // release the lock protecting windows in write mode
264    remote_rwlock_wr_release( windows_lock_xp );
265
266#if DEBUG_DEV_FBF
267cycle = (uint32_t)hal_get_cycles();
268if( DEBUG_DEV_FBF < cycle )
269printk("\n[%s] thread[%x,%x] exit / wid %d / buffer %x / cycle %d\n",
270__FUNCTION__ , this->process->pid, this->trdid, wid , window->buffer, cycle );
271#endif
272
273#if (DEBUG_DEV_FBF & 1)
274hal_vmm_display( ref_xp , true );
275#endif
276
277    // return pointer on allocated buffer
278    *user_buffer = vseg_base;
279
280    return wid;
281
282}  // end dev_fbf_create_window()
283
284////////////////////////////////////////////////////////////////////////////////////////
285// This static function is called by the dev_fbf_display() function.
286// For a partial FBF line, identified by the <f_line>, <f_p_min>, <f_p_max> arguments
287// in FBF reference, and for one remote window, identified by the <window_xp> argument,
288// it updates the target buffer identified by <t_buffer>, and containing exactly
289// (f_p_max - f_p_min) pixels.
290// Depending on the actual overlap between the window and the <t_buffer> representing
291// the partial FBF line, it moves up to (f_p_max - f_p_min) pixels from the window
292// buffer to the target buffer. The number of moved pixels can be nul if no overlap.
293////////////////////////////////////////////////////////////////////////////////////////
294// @ f_line     : [in]  line index in FBF reference (from 0 to fbf_height-1).
295// @ f_p_min    : [in]  first pixel in FBF line.
296// @ f_p_max    : [in]  last pixel in FBF line (excluded).
297// @ window_xp  : [in]  extended pointer on checked window .
298// @ t_buffer   : [out] local pointer on target buffer to be updated.
299///////////////////////////////////////////////////////////////////////////////////////
300__attribute__ ((noinline)) static void handle_one_window( uint32_t  f_line,
301                                                          uint32_t  f_p_min,
302                                                          uint32_t  f_p_max,
303                                                          xptr_t    window_xp,
304                                                          uint8_t * t_buffer )
305{
306    // get remote window descriptor cluster and local pointer
307    cxy_t          window_cxy = GET_CXY( window_xp );
308    fbf_window_t * window_ptr = GET_PTR( window_xp );
309
310    // get remote window min/max coordinates in FBF reference
311    uint32_t  w_l_min    = hal_remote_l32( XPTR( window_cxy , &window_ptr->l_min ) );
312    uint32_t  w_p_min    = hal_remote_l32( XPTR( window_cxy , &window_ptr->p_min ) );
313    uint32_t  w_height   = hal_remote_l32( XPTR( window_cxy , &window_ptr->height ) );
314    uint32_t  w_width    = hal_remote_l32( XPTR( window_cxy , &window_ptr->width  ) );
315    uint32_t  w_l_max    = w_l_min + w_height;
316    uint32_t  w_p_max    = w_p_min + w_width;
317
318    // does nothing if partial FBF line does not overlap the window
319    if( (f_line < w_l_min)  || (f_line >= w_l_max) ||
320        (f_p_max < w_p_min) || (f_p_min >= w_p_max) ) return;
321
322    // get pointer on window buffer in user space
323    uint8_t * w_buffer = hal_remote_lpt( XPTR( window_cxy , &window_ptr->buffer ) ); 
324
325    // get min & max indexes for pixels to be moved in FBF reference
326    uint32_t f_pixel_min = (f_p_min < w_p_min) ? w_p_min : f_p_min;
327    uint32_t f_pixel_max = (f_p_max < w_p_max) ? f_p_max : w_p_max;
328
329    // compute number of pixels to move from w_buffer to f_buffer
330    uint32_t npixels = f_pixel_max - f_pixel_min;
331
332    // compute offset in target buffer
333    uint32_t t_offset = f_pixel_min - f_p_min; 
334
335    // compute line index in window 
336    uint32_t w_line = f_line - w_l_min;
337
338    // compute offset in window buffer
339    uint32_t w_offset = (w_line * w_height) + f_pixel_min - w_p_min;
340
341    // move pixels from w_buffer (user space) to t_buffer in kernel space
342    hal_copy_from_uspace( XPTR( local_cxy  , &t_buffer[t_offset]  ),
343                          &w_buffer[w_offset], 
344                          npixels );
345
346}  // end handle_one_window()
347
348////////////////////////////////////////////////////////////////////////////////////////
349// This static function is called by dev_fbf_refresh_window(), dev_fbf_move_window(),
350// dev_fbf_resize_window(), and dev_fbf_delete_window(). It updates all lines of the
351// window identified by the <window_xp>, <line_first>, and <line_last>> arguments.
352// It scan all registered windows to take into account the overlap priorities defined
353// by the windows xlist. It does not take the lock protecting the xlist, that must be
354// taken by the calling function.
355////////////////////////////////////////////////////////////////////////////////////////
356// @ window_xp  : [in]  extended pointer on window defining the FBF pixels to refresh.
357// @ line_first : [in]  first line index.
358// @ line_last  : [in]  last line index (excluded).
359////////////////////////////////////////////////////////////////////////////////////////
360error_t fbf_update( xptr_t    window_xp,
361                    uint32_t  line_first,
362                    uint32_t  line_last )
363{
364    uint32_t       line;                // iterator to scan the FBF lines
365    uint32_t       pixel;               // iterator to scan pixels in one FBF line
366    xptr_t         iter_xp;             // iterator to scan the list of windows
367    error_t        error;
368
369    // this intermediate buffer stores one line in
370    // target window, to handle other windows overlap
371    uint8_t       line_buffer[CONFIG_FBF_WINDOWS_MAX_WIDTH];
372
373    // get pointer on calling thread and core lid
374    thread_t  * this = CURRENT_THREAD;
375
376    // get window cluster and local pointer
377    cxy_t          window_cxy = GET_CXY( window_xp );
378    fbf_window_t * window_ptr = GET_PTR( window_xp );
379
380#if DEBUG_DEV_FBF
381uint32_t wid   = hal_remote_l32( XPTR( window_cxy , &window_ptr->wid ) );
382uint32_t lid   = this->core->lid;
383uint32_t cycle = (uint32_t)hal_get_cycles();
384if( DEBUG_DEV_FBF < cycle )
385printk("\n[%s] core[%x,%d] enter / wid %d / cycle %d\n",
386__FUNCTION__, local_cxy, lid, wid, cycle );
387#endif
388
389    // get pointers on FBF chdev
390    xptr_t      fbf_xp  = chdev_dir.fbf[0];
391    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
392    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
393
394    // get frame buffer width
395    uint32_t fbf_width  = hal_remote_l32( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.width ) );
396
397    // get pointer on driver command function
398    dev_cmd_t * cmd = hal_remote_lpt( XPTR( fbf_cxy , &fbf_ptr->cmd ) );
399
400    // build extended pointers on windows xlist root
401    xptr_t  windows_root_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
402
403    // get window size and coordinates
404    uint32_t  p_min     = hal_remote_l32( XPTR( window_cxy , &window_ptr->p_min ) );
405    uint32_t  l_min     = hal_remote_l32( XPTR( window_cxy , &window_ptr->l_min ) );
406    uint32_t  w_pixels  = hal_remote_l32( XPTR( window_cxy , &window_ptr->width  ) );
407
408    error = 0;
409
410    // loop on target window lines (FBF coordinates)
411    for( line = l_min + line_first ; line < (l_min + line_last) ; line++ )
412    {
413        // reset the line buffer to default value
414        for( pixel = 0 ; pixel < w_pixels ; pixel++ ) line_buffer[pixel] = 127;
415
416        // loop on all windows
417        XLIST_FOREACH( windows_root_xp , iter_xp )
418        {
419            // get pointers on remote window
420            xptr_t         tgt_xp  = XLIST_ELEMENT( iter_xp , fbf_window_t , xlist );
421            fbf_window_t * tgt_ptr = GET_PTR( window_xp );
422            cxy_t          tgt_cxy = GET_CXY( window_xp );
423
424            bool_t hidden = hal_remote_l32( XPTR( tgt_cxy , &tgt_ptr->hidden ) );
425
426            // fill the line_buf for this window if not hidden
427            if( hidden == false ) handle_one_window( line,               // line index
428                                                     p_min,              // pixel_min
429                                                     p_min + w_pixels,   // pixel_max
430                                                     tgt_xp,             // window_xp     
431                                                     line_buffer );     
432        }  // end for windows
433
434        // compute offset in FBF
435        uint32_t fbf_offset = p_min + (line * fbf_width);
436
437        // register command in calling thread descriptor
438        this->fbf_cmd.dev_xp    = fbf_xp;
439        this->fbf_cmd.type      = FBF_DRIVER_KERNEL_WRITE;
440        this->fbf_cmd.buffer    = line_buffer;
441        this->fbf_cmd.npixels   = w_pixels;
442        this->fbf_cmd.offset    = fbf_offset;
443
444        // call driver to display one line
445        cmd( XPTR( local_cxy , this ) );
446
447        error |= this->fbf_cmd.error;
448   
449    }  // end for lines
450
451#if DEBUG_DEV_FBF
452cycle = (uint32_t)hal_get_cycles();
453if( DEBUG_DEV_FBF < cycle )
454printk("\n[%s] core[%x,%d] exit / wid %d / cycle %d\n",
455__FUNCTION__, local_cxy, this->core->lid, wid, cycle );
456#endif
457
458    // return I/O operation status
459    return error;
460
461}  // end fbf_update()
462
463//////////////////////////////////////////////
464error_t dev_fbf_delete_window( uint32_t  wid )
465{
466    kmem_req_t     req;
467
468    thread_t  * this    = CURRENT_THREAD;
469    process_t * process = this->process;
470
471#if DEBUG_DEV_FBF
472uint32_t   cycle = (uint32_t)hal_get_cycles();
473if( DEBUG_DEV_FBF < cycle )
474printk("\n[%s] thread[%x,%x] enters : wid %d / cycle %d\n",
475__FUNCTION__ , process->pid, this->trdid, wid, cycle );
476#endif
477
478    // get cluster and pointers on FBF chdev
479    xptr_t      fbf_xp  = chdev_dir.fbf[0];
480    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
481    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
482
483    // build extended pointers on windows lock, and wid allocator
484    xptr_t windows_lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
485    xptr_t wid_bitmap_xp   = XPTR( fbf_cxy ,  fbf_ptr->ext.fbf.windows_bitmap );
486
487    // build extended pointer on relevant entry in windows_tbl[] array
488    xptr_t  windows_tbl_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_tbl[wid] );
489
490    // get extended pointer on remote window descriptor
491    xptr_t window_xp  = hal_remote_l64( windows_tbl_xp );
492
493    if( window_xp == XPTR_NULL )
494    {
495        printk("\n[ERROR] in %s / thread[%x,%x] / wid %d non registered\n",
496        __FUNCTION__, process->pid, this->trdid, wid );
497        return -1;
498    }
499
500    // get cluster and local pointer on remote window
501    cxy_t          window_cxy = GET_CXY( window_xp );
502    fbf_window_t * window_ptr = GET_PTR( window_xp );
503
504    // get process owner PID
505    pid_t owner_pid = hal_remote_l32( XPTR( window_cxy , &window_ptr->pid ) );
506
507    // check caller PID / owner PID
508    if( owner_pid != process->pid )
509    {
510        printk("\n[ERROR] in %s : caller PID (%x) != owner PID (%x)\n",
511        __FUNCTION__, process->pid , owner_pid );
512        return -1;
513    }
514
515    // get associated buffer, and number of lines
516    uint8_t  * buffer = hal_remote_lpt( XPTR( window_cxy , &window_ptr->buffer ) );
517    uint32_t   nlines = hal_remote_l32( XPTR( window_cxy , &window_ptr->height ) );
518
519    // 1. take the lock protecting windows in write mode
520    remote_rwlock_wr_acquire( windows_lock_xp );
521
522    // 2. update the FBF window
523    fbf_update( window_xp , 0 , nlines );
524
525    // 3. remove the window from windows_tbl[] array
526    hal_remote_s64( windows_tbl_xp , XPTR_NULL );
527
528    // 4. remove the window from xlist     
529    xlist_unlink( XPTR( window_cxy , &window_ptr->xlist ) );
530
531    // 5. release wid to bitmap
532    bitmap_remote_clear( wid_bitmap_xp , wid );
533
534    // 6. release the lock protecting windows in write mode
535    remote_rwlock_wr_release( windows_lock_xp );
536 
537    // 7. release memory allocated for window descriptor
538    req.type = KMEM_KCM;
539    req.ptr  = window_ptr;
540    kmem_remote_free( window_cxy , &req );
541
542    // 8. release the associated vseg
543    vmm_global_delete_vseg( process , (intptr_t)buffer );
544   
545#if DEBUG_DEV_FBF
546cycle = (uint32_t)hal_get_cycles();
547if( DEBUG_DEV_FBF < cycle )
548printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
549__FUNCTION__ , process->pid, this->trdid, cycle );
550#endif
551
552    return 0;
553
554}  // end dev_fbf_delete_window()
555
556////////////////////////////////////////////
557error_t dev_fbf_move_window( uint32_t  wid,
558                             uint32_t  l_min,
559                             uint32_t  p_min )
560{
561    thread_t  * this    = CURRENT_THREAD;
562    process_t * process = this->process;
563
564#if DEBUG_DEV_FBF
565uint32_t   cycle = (uint32_t)hal_get_cycles();
566if( DEBUG_DEV_FBF < cycle )
567printk("\n[%s] thread[%x,%x] enters : wid %d / l_min %d / p_min %d / cycle %d\n",
568__FUNCTION__ , process->pid, this->trdid, wid, l_min, p_min, cycle );
569#endif
570
571    // get cluster and pointers on FBF chdev
572    xptr_t      fbf_xp  = chdev_dir.fbf[0];
573    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
574    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
575
576    // build extended pointers on windows lock and root
577    xptr_t windows_lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
578    xptr_t windows_root_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
579
580    // build extended pointer on relevant entry in windows_tbl[] array
581    xptr_t  windows_tbl_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_tbl[wid] );
582
583    // get extended pointer on remote window descriptor
584    xptr_t window_xp  = hal_remote_l64( windows_tbl_xp );
585
586    if( window_xp == XPTR_NULL )
587    {
588        printk("\n[ERROR] in %s / thread[%x,%x] / wid %d non registered\n",
589        __FUNCTION__, process->pid, this->trdid, wid );
590        return -1;
591    }
592
593    // get cluster and local pointer for remote window
594    cxy_t          window_cxy = GET_CXY( window_xp );
595    fbf_window_t * window_ptr = GET_PTR( window_xp );
596
597    // get process owner PID, coordinates, and number of lines
598    pid_t    owner_pid = hal_remote_l32( XPTR( window_cxy , &window_ptr->pid ) );
599    uint32_t p_zero    = hal_remote_l32( XPTR( window_cxy , &window_ptr->p_min ) );
600    uint32_t l_zero    = hal_remote_l32( XPTR( window_cxy , &window_ptr->l_min ) );
601    uint32_t nlines    = hal_remote_l32( XPTR( window_cxy , &window_ptr->height ) );
602
603    // check caller PID / owner PID
604    if( owner_pid != process->pid )
605    {
606        printk("\n[ERROR] in %s : caller PID (%x) != owner PID (%x)\n",
607        __FUNCTION__, process->pid , owner_pid );
608        return -1;
609    }
610
611    // does nothing if no change
612    if( (p_zero == p_min) && (l_zero == l_min) )  return 0;
613
614    // 1. take the lock protecting windows in write mode
615    remote_rwlock_wr_acquire( windows_lock_xp );
616
617#if ( DEBUG_DEV_FBF & 1 )
618printk("\n[%s] lock taken\n", __FUNCTION__ );
619#endif
620
621    // 2. gives the window the lowest priority
622    xptr_t xlist_entry_xp =  XPTR( window_cxy , &window_ptr->xlist );
623    xlist_unlink( xlist_entry_xp );
624    xlist_add_first( windows_root_xp , xlist_entry_xp );
625
626#if ( DEBUG_DEV_FBF & 1 )
627printk("\n[%s] set low priority \n", __FUNCTION__ );
628#endif
629
630    // 3. set the "hidden" flag in window descriptor
631    hal_remote_s32( XPTR( window_cxy , &window_ptr->hidden ) , true );
632
633#if ( DEBUG_DEV_FBF & 1 )
634printk("\n[%s] hidden set\n", __FUNCTION__ );
635#endif
636
637    // 4. refresh the FBF for the current window position
638    fbf_update( window_xp , 0 , nlines );
639
640#if ( DEBUG_DEV_FBF & 1 )
641printk("\n[%s] refreshed old position\n", __FUNCTION__ );
642#endif
643
644    // 5. set the new coordinates in the window descriptor,
645    hal_remote_s32( XPTR( window_cxy , &window_ptr->l_min ), l_min );
646    hal_remote_s32( XPTR( window_cxy , &window_ptr->p_min ), p_min );
647
648#if ( DEBUG_DEV_FBF & 1 )
649printk("\n[%s] l_min & p_min updated\n", __FUNCTION__ );
650#endif
651
652    // 6. gives the window the highest priority
653    xlist_unlink( xlist_entry_xp );
654    xlist_add_last( windows_root_xp , xlist_entry_xp );
655
656#if ( DEBUG_DEV_FBF & 1 )
657printk("\n[%s] set high priority\n", __FUNCTION__ );
658#endif
659
660    // 7. reset the "hidden" flag in window descriptor
661    hal_remote_s32( XPTR( window_cxy , &window_ptr->hidden ) , false );
662
663#if ( DEBUG_DEV_FBF & 1 )
664printk("\n[%s] hidden reset\n", __FUNCTION__ );
665#endif
666
667    // 8. refresh the FBF for the new window position
668    fbf_update( window_xp , 0 , nlines );
669
670#if ( DEBUG_DEV_FBF & 1 )
671printk("\n[%s] refresh new position\n", __FUNCTION__ );
672#endif
673
674    // 9. release the lock protecting windows in write mode
675    remote_rwlock_wr_release( windows_lock_xp );
676 
677#if DEBUG_DEV_FBF
678cycle = (uint32_t)hal_get_cycles();
679if( DEBUG_DEV_FBF < cycle )
680printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
681__FUNCTION__ , process->pid, this->trdid, cycle );
682#endif
683
684    return 0;
685
686}  // end dev_fbf_move_window()
687
688/////////////////////////////////////////////
689error_t dev_fbf_resize_window( uint32_t  wid,
690                               uint32_t  width,
691                               uint32_t  height )
692{
693    thread_t  * this    = CURRENT_THREAD;
694    process_t * process = this->process;
695
696#if DEBUG_DEV_FBF
697uint32_t   cycle = (uint32_t)hal_get_cycles();
698if( DEBUG_DEV_FBF < cycle )
699printk("\n[%s] thread[%x,%x] enters : wid %d / width %d / height %d / cycle %d\n",
700__FUNCTION__ , process->pid , this->trdid , wid, width , height , cycle );
701#endif
702
703    // get cluster and pointers on FBF chdev
704    xptr_t      fbf_xp  = chdev_dir.fbf[0];
705    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
706    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
707
708    // build extended pointers on windows lock and root
709    xptr_t windows_lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
710    xptr_t windows_root_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
711
712    // build extended pointer on relevant entry in windows_tbl[] array
713    xptr_t  windows_tbl_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_tbl[wid] );
714
715    // get extended pointer on remote window descriptor
716    xptr_t window_xp  = hal_remote_l64( windows_tbl_xp );
717
718    if( window_xp == XPTR_NULL )
719    {
720        printk("\n[ERROR] in %s / thread[%x,%x] / wid %d non registered\n",
721        __FUNCTION__, process->pid, this->trdid, wid );
722        return -1;
723    }
724
725    // get cluster and local pointer for remote window
726    cxy_t          window_cxy = GET_CXY( window_xp );
727    fbf_window_t * window_ptr = GET_PTR( window_xp );
728
729    // get process owner PID, width, height, and buffer
730    pid_t    owner_pid = hal_remote_l32( XPTR( window_cxy , &window_ptr->pid ) );
731    uint32_t nlines    = hal_remote_l32( XPTR( window_cxy , &window_ptr->height ) );
732    uint32_t npixels   = hal_remote_l32( XPTR( window_cxy , &window_ptr->width ) );
733    void   * base      = hal_remote_lpt( XPTR( window_cxy , &window_ptr->buffer ) );
734
735    // check caller PID / owner PID
736    if( owner_pid != process->pid )
737    {
738        printk("\n[ERROR] in %s : caller PID (%x) != owner PID (%x)\n",
739        __FUNCTION__, process->pid , owner_pid );
740        return -1;
741    }
742
743    // does nothing if no change
744    if( (width == npixels) && (height == nlines) ) return 0;
745
746    // compute old_size and new size
747    uint32_t old_size = nlines * npixels;
748    uint32_t new_size = width * height;
749
750    // 1. take the lock protecting windows in write mode
751    remote_rwlock_wr_acquire( windows_lock_xp );
752
753#if ( DEBUG_DEV_FBF & 1 )
754printk("\n[%s] lock taken\n", __FUNCTION__ );
755#endif
756
757    // 2. gives the window the lowest priority (remove, then add first)
758    xptr_t xlist_entry_xp =  XPTR( window_cxy , &window_ptr->xlist );
759    xlist_unlink( xlist_entry_xp );
760    xlist_add_first( windows_root_xp , xlist_entry_xp );
761
762#if ( DEBUG_DEV_FBF & 1 )
763printk("\n[%s] set low priority\n", __FUNCTION__ );
764#endif
765
766    // 3. set the "hidden" flag in window descriptor
767    hal_remote_s32( XPTR( window_cxy , &window_ptr->hidden ) , true );
768
769#if ( DEBUG_DEV_FBF & 1 )
770printk("\n[%s] hidden set\n", __FUNCTION__ );
771#endif
772
773    // 4. refresh the FBF for the current window size
774    fbf_update( window_xp , 0 , nlines );
775
776#if ( DEBUG_DEV_FBF & 1 )
777printk("\n[%s] refreshed old window\n", __FUNCTION__ );
778#endif
779
780    // 5. set the new width & height in the window descriptor,
781    hal_remote_s32( XPTR( window_cxy , &window_ptr->width  ), width );
782    hal_remote_s32( XPTR( window_cxy , &window_ptr->height ), height );
783
784#if ( DEBUG_DEV_FBF & 1 )
785printk("\n[%s] width & height updated\n", __FUNCTION__ );
786#endif
787
788    // 6. resize vseg if required
789    vmm_global_resize_vseg( process, (intptr_t)base, (intptr_t)base, width * height );
790
791#if ( DEBUG_DEV_FBF & 1 )
792printk("\n[%s] vseg resized\n", __FUNCTION__ );
793#endif
794
795    // 7. fill buffer extension if required
796    if( new_size > old_size )  memset( base + old_size , 0 , new_size - old_size );
797
798#if ( DEBUG_DEV_FBF & 1 )
799printk("\n[%s] buffer extension initialized\n", __FUNCTION__ );
800#endif
801
802    // 8. gives the window the highest priority
803    xlist_unlink( xlist_entry_xp );
804    xlist_add_last( windows_root_xp , xlist_entry_xp );
805
806#if ( DEBUG_DEV_FBF & 1 )
807printk("\n[%s] set high priority\n", __FUNCTION__ );
808#endif
809
810    // 9. reset the "hidden" flag in window descriptor
811    hal_remote_s32( XPTR( window_cxy , &window_ptr->hidden ) , false );
812
813#if ( DEBUG_DEV_FBF & 1 )
814printk("\n[%s] hidden reset\n", __FUNCTION__ );
815#endif
816
817    // 10. refresh the FBF for the new window position
818    fbf_update( window_xp , 0 , height );
819
820#if ( DEBUG_DEV_FBF & 1 )
821printk("\n[%s] refresh new position\n", __FUNCTION__ );
822#endif
823
824    // 11. release the lock protecting windows in write mode
825    remote_rwlock_wr_release( windows_lock_xp );
826 
827#if DEBUG_DEV_FBF
828cycle = (uint32_t)hal_get_cycles();
829if( DEBUG_DEV_FBF < cycle )
830printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
831__FUNCTION__ , process->pid, this->trdid, cycle );
832#endif
833
834    return 0;
835
836}  // end dev_fbf_resize_window()
837
838///////////////////////////////////////////////
839error_t dev_fbf_refresh_window( uint32_t  wid,
840                                uint32_t  line_first,
841                                uint32_t  line_last )
842{
843    // get local pointers on calling thread and process
844    thread_t  * this    = CURRENT_THREAD;
845    process_t * process = this->process;
846
847#if DEBUG_DEV_FBF
848uint32_t   cycle = (uint32_t)hal_get_cycles();
849if( DEBUG_DEV_FBF < cycle )
850printk("\n[%s] thread[%x,%x] enters for wid %d / first %d / last %d / cycle %d\n",
851__FUNCTION__ , process->pid, this->trdid, wid, line_first, line_last, cycle );
852#endif
853
854    // get cluster and pointers on FBF chdev
855    xptr_t      fbf_xp  = chdev_dir.fbf[0];
856    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
857    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
858
859    // build extended pointer on windows lock
860    xptr_t  windows_lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
861
862    // build extended pointer on relevant entry in windows_tbl[] array
863    xptr_t  windows_tbl_xp  = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_tbl[wid] );
864
865    // get pointers on remote window descriptor
866    xptr_t         window_xp  = hal_remote_l64( windows_tbl_xp );
867    cxy_t          window_cxy = GET_CXY( window_xp );
868    fbf_window_t * window_ptr = GET_PTR( window_xp );
869
870    // check <wid> argument
871    if( window_xp == XPTR_NULL )
872    {
873        printk("\n[ERROR] in %s / thread[%x,%x] / wid %d non registered\n",
874        __FUNCTION__, process->pid, this->trdid, wid );
875        return -1;
876    }
877
878    // get process owner PID
879    pid_t owner_pid = hal_remote_l32( XPTR( window_cxy , &window_ptr->pid ) );
880
881    // check caller PID / owner PID
882    if( owner_pid != process->pid )
883    {
884        printk("\n[ERROR] in %s : caller PID (%x) != owner PID (%x)\n",
885        __FUNCTION__, process->pid , owner_pid );
886        return -1;
887    }
888
889    // get number of lines in window
890    uint32_t nlines = hal_remote_l32( XPTR( window_cxy , &window_ptr->height ) ); 
891
892    // check <line_first> and <line_last> arguments
893    if( (line_first >= nlines) || (line_last > nlines) || (line_first >= line_last) )
894    {
895        printk("\n[ERROR] in %s : illegal (l_first %d , l_last %d) / height %d\n",
896        __FUNCTION__, line_first, line_last, nlines );
897        return -1;
898    }
899
900    // take the lock protecting windows xlist in read mode
901    remote_rwlock_rd_acquire( windows_lock_xp );
902
903    // update FBF
904    fbf_update( window_xp , line_first , line_last );
905
906    // release the lock protecting windows xlist in write mode
907    remote_rwlock_rd_release( windows_lock_xp );
908
909#if DEBUG_DEV_FBF
910cycle = (uint32_t)hal_get_cycles();
911if( DEBUG_DEV_FBF < cycle )
912printk("\n[%s] thread[%x,%x] exit for wid %d / cycle %d\n",
913__FUNCTION__, process->pid, this->trdid, wid, cycle );
914#endif
915
916    return 0;
917
918}  // end dev_fbf_refresh_window()
919
920///////////////////////////////////////////////
921// TODO Deprecated : january 2020 [AG]
922///////////////////////////////////////////////
923error_t dev_fbf_move_data( bool_t     is_write,
924                           void     * user_buffer,
925                           uint32_t   npixels,
926                           uint32_t   offset )
927{
928    // get pointer on calling thread
929    thread_t * this = CURRENT_THREAD;
930
931#if DEBUG_DEV_FBF
932uint32_t   cycle = (uint32_t)hal_get_cycles();
933if( DEBUG_DEV_FBF < cycle )
934printk("\n[%s] thread[%x,%x] :  buffer %x / npixels %d / offset %x / cycle %d\n",
935__FUNCTION__ , this->process->pid, this->trdid, 
936user_buffer, npixels, offset, cycle );
937#endif
938
939    // get pointers on FBF chdev
940    xptr_t      fbf_xp  = chdev_dir.fbf[0];
941    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
942    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
943
944    // get frame buffer width and height
945    uint32_t width  = hal_remote_l32 ( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.width ) );
946    uint32_t height = hal_remote_l32 ( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.height ) );
947
948    // check offset and npixels versus FBF size
949    if( ((offset + npixels) > (width * height)) )
950    {
951        printk("\n[ERROR] in %s : offset (%d) + npixels (%d) / width (%d) / height (%d)\n",
952        __FUNCTION__, offset, npixels, width, height ); 
953        return -1;
954    }
955
956    // register command in calling thread descriptor
957    this->fbf_cmd.dev_xp    = fbf_xp;
958    this->fbf_cmd.type      = is_write ? FBF_DRIVER_USER_WRITE : FBF_DRIVER_USER_READ;
959    this->fbf_cmd.buffer    = user_buffer;
960    this->fbf_cmd.offset    = offset;
961    this->fbf_cmd.npixels   = npixels;
962
963    // get driver command function
964    dev_cmd_t * cmd = (dev_cmd_t *)hal_remote_lpt( XPTR( fbf_cxy , &fbf_ptr->cmd ) );
965
966    // call driver
967    cmd( XPTR( local_cxy , this ) );
968
969    error_t error = this->fbf_cmd.error;
970
971#if DEBUG_DEV_FBF
972cycle = (uint32_t)hal_get_cycles();
973if( DEBUG_DEV_FBF < cycle )
974printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
975__FUNCTION__ , this->process->pid, this->trdid, cycle );
976#endif
977
978    // return I/O operation status
979    return error;
980
981}  // end dev_fbf_move_data()
982
983
Note: See TracBrowser for help on using the repository browser.