source: trunk/kernel/devices/dev_fbf.c

Last change on this file was 683, checked in by alain, 13 months ago

All modifications required to support the <tcp_chat> application
including error recovery in case of packet loss.A

File size: 40.4 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_ACTIVE_WINDOW  )  return "ACTIVE_WINDOW";
51    else if( cmd_type == FBF_DELETE_WINDOW  )  return "DELETE_WINDOW";
52    else if( cmd_type == FBF_MOVE_WINDOW    )  return "MOVE_WINDOW";
53    else if( cmd_type == FBF_REFRESH_WINDOW )  return "REFRESH_WINDOW";
54    else if( cmd_type == FBF_FRONT_WINDOW   )  return "FRONT_WINDOW";
55    else if( cmd_type == FBF_RESIZE_WINDOW  )  return "RESIZE_WINDOW";
56
57    else if( cmd_type == FBF_DIRECT_WRITE   )  return "DIRECT_WRITE";
58    else if( cmd_type == FBF_DIRECT_READ    )  return "DIRECT_READ";
59    else                                       return "undefined";
60}
61
62////////////////////////////////////////////////
63xptr_t dev_fbf_get_xptr_from_wid( uint32_t wid )
64{
65    thread_t  * this  = CURRENT_THREAD;
66    pid_t       pid   = this->process->pid;
67    trdid_t     trdid = this->trdid;
68
69    // get cluster and pointers on FBF chdev
70    xptr_t      fbf_xp  = chdev_dir.fbf[0];
71    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
72    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
73
74    // build extended pointer on windows_tbl[wid]
75    xptr_t entry_xp  = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_tbl[wid] );
76
77    // get pointers on searched window
78    xptr_t         window_xp  = hal_remote_l64( entry_xp );
79    cxy_t          window_cxy = GET_CXY( window_xp );
80    fbf_window_t * window_ptr = GET_PTR( window_xp );
81
82    if( window_xp == XPTR_NULL )
83    {
84        printk("\n[ERROR] in %s / client thread[%x,%x] request a non registered wid (%d)\n",
85        __FUNCTION__, pid, trdid, wid );
86        return XPTR_NULL;
87    }
88
89    // get owner process PID from window descriptor
90    pid_t owner_pid = hal_remote_l32( XPTR( window_cxy , &window_ptr->pid ) );
91
92    if( pid != owner_pid )
93    {
94        printk("\n[ERROR] in %s / client thread[%x,%x] not owner of wid (%d) / owner is (%x)\n",
95        __FUNCTION__, pid, trdid, owner_pid, wid );
96        return XPTR_NULL;
97    }
98
99    return window_xp;
100
101}  // end dev_fbf_get_xptr_from_wid()
102
103////////////////////////////////////
104void dev_fbf_init( chdev_t  * fbf )
105{
106    uint32_t wid;
107
108    // set chdev name
109    strcpy( fbf->name, "fbf" );
110
111    // initialize lock protecting the windows
112    remote_rwlock_init( XPTR( local_cxy , &fbf->ext.fbf.windows_lock ),
113                        LOCK_FBF_WINDOWS ); 
114
115    // initialize root of windows xlist
116    xlist_root_init( XPTR( local_cxy , &fbf->ext.fbf.windows_root ) );
117
118    // initialize windows_tbl[] array
119    for( wid = 0 ; wid < CONFIG_FBF_WINDOWS_MAX_NR ; wid++ ) 
120    {
121        fbf->ext.fbf.windows_tbl[wid] = XPTR_NULL;
122    }
123
124    // initialize wid allocator bitmap
125    bitmap_init( fbf->ext.fbf.windows_bitmap , CONFIG_FBF_WINDOWS_MAX_NR );
126
127    // call driver init function to initialize the harware FBF
128    // and initialize the width, height, and subsampling FBF chdev fields
129    hal_drivers_fbf_init( fbf );
130
131}  // end dev_fbf_init()
132
133//////////////////////////////////////////
134void dev_fbf_get_config( uint32_t * width,
135                         uint32_t * height,
136                         uint32_t * type )
137{
138    // get extended pointer on FBF chdev descriptor
139    xptr_t  dev_xp = chdev_dir.fbf[0];
140
141assert( __FUNCTION__, (dev_xp != XPTR_NULL) , "undefined FBF chdev descriptor" );
142
143    // get FBF chdev cluster and local pointer
144    cxy_t     dev_cxy = GET_CXY( dev_xp );
145    chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
146
147    // return values
148    *width  = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.width ) );
149    *height = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.height ) );
150    *type   = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.subsampling ) );
151
152}  // end dev_fbf_get_config()
153
154/////////////////////////////////////////////////
155uint32_t dev_fbf_create_window( uint32_t   nlines,
156                                uint32_t   npixels,
157                                uint32_t   l_min,
158                                uint32_t   p_min,
159                                intptr_t * user_buffer )
160{
161    fbf_window_t * window;      // window descriptor (created in local cluster)
162    vseg_t       * vseg;        // vseg descriptor (created in reference cluster)
163    intptr_t       vseg_base;   // vseg base address in user space 
164
165    // get local pointers on calling thread and process
166    thread_t  * this    = CURRENT_THREAD;
167    process_t * process = this->process;
168
169#if DEBUG_DEV_FBF
170uint32_t   cycle = (uint32_t)hal_get_cycles();
171if( DEBUG_DEV_FBF < cycle )
172printk("\n[%s] thread[%x,%x] enter : nlines %d / npixels %d / l_min %d / p_min %d / cycle %d\n",
173__FUNCTION__ , process->pid, this->trdid, nlines, npixels, l_min, p_min, cycle );
174#endif
175
176    // get cluster and pointers on FBF chdev
177    xptr_t      fbf_xp  = chdev_dir.fbf[0];
178    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
179    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
180
181// check fbf_xp definition
182assert( __FUNCTION__, (fbf_xp != XPTR_NULL) , "undefined FBF chdev descriptor" );
183
184    // get FBF width and height
185    uint32_t fbf_width  = hal_remote_l32( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.width ) );
186    uint32_t fbf_height = hal_remote_l32( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.height ) );
187
188    // check new window size and coordinates
189    if( (((l_min + nlines) > fbf_height) || ((p_min + npixels) > fbf_width)) )
190    {
191        printk("\n[ERROR] in %s / thread[%x,%x]" 
192        "illegal new coordinates (%d,%d) for window (%d,%d) in fbf (%d,%d)\n",
193        process->pid, this->trdid, p_min, l_min, npixels, nlines, fbf_width, fbf_height );
194        return -1;
195    }
196
197    // build extended pointers on windows lock, root, and wid allocator
198    xptr_t windows_lock_xp   = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
199    xptr_t windows_root_xp   = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
200    xptr_t windows_bitmap_xp = XPTR( fbf_cxy ,  fbf_ptr->ext.fbf.windows_bitmap );
201 
202    // allocate memory for the window descriptor in local cluster
203    window  = kmem_alloc( bits_log2(sizeof(fbf_window_t)) , AF_ZERO );
204
205    if( window == NULL )
206    {
207        printk("\n[ERROR] in %s / thread[%x,%x] cannot allocate window descriptor\n",
208        __FUNCTION__, process->pid, this->trdid );
209        return -1;
210    }
211
212#if (DEBUG_DEV_FBF & 1)
213cycle = (uint32_t)hal_get_cycles();
214if( DEBUG_DEV_FBF < cycle )
215printk("\n[%s] thread[%x,%x] created window descriptor %x / cycle %d\n",
216__FUNCTION__ , process->pid, this->trdid, window, cycle );
217#endif
218
219    // getpointers on reference process
220    xptr_t      ref_xp  = process->ref_xp;
221    process_t * ref_ptr = GET_PTR( ref_xp );
222    cxy_t       ref_cxy = GET_CXY( ref_xp );
223
224    // allocate a new vseg, and introduce it in the reference process VSL
225    if( ref_cxy == local_cxy )
226    {
227        vseg = vmm_create_vseg( process,            // owner process
228                                VSEG_TYPE_ANON,     // localised, public
229                                0,                  // base, unused for ANON
230                                nlines * npixels,   // size
231                                0,                  // file_offset, unused for ANON
232                                0,                  // file_size, unused for ANON
233                                XPTR_NULL,          // mapper_xp, unused for ANON
234                                local_cxy );        // mapping cluster
235    }
236    else
237    {
238        rpc_vmm_create_vseg_client( ref_cxy,
239                                    ref_ptr,
240                                    VSEG_TYPE_ANON,
241                                    0,                 // base, unused for ANON
242                                    nlines * npixels,  // size
243                                    0,                 // file_offset, unused for ANON
244                                    0,                 // file size, unused for ANON
245                                    XPTR_NULL,         // mapper_xp, unused for ANON
246                                    local_cxy,
247                                    &vseg );
248    } 
249       
250    if( vseg == NULL )
251    {
252        printk("\n[ERROR] in %s / thread[%x,%x] cannot create vseg in reference cluster\n",
253        __FUNCTION__, process->pid, this->trdid );
254        kmem_free( window , bits_log2(sizeof(fbf_window_t)) );
255        return -1;
256    }
257
258    // get vseg base
259    vseg_base = (intptr_t)hal_remote_lpt( XPTR( ref_cxy , &vseg->min ) );
260
261#if (DEBUG_DEV_FBF & 1)
262cycle = (uint32_t)hal_get_cycles();
263if( DEBUG_DEV_FBF < cycle )
264printk("\n[%s] thread[%x,%x] allocated vseg / base %x / cycle %d\n",
265__FUNCTION__ , process->pid, this->trdid, vseg_base, cycle );
266#endif
267
268    // take the lock protecting windows in write mode
269    remote_rwlock_wr_acquire( windows_lock_xp );
270
271    // allocate a wid from allocator in FBF descriptor extension
272    uint32_t wid = bitmap_remote_alloc( windows_bitmap_xp , CONFIG_FBF_WINDOWS_MAX_NR );
273
274    if( wid == 0xFFFFFFFF )
275    {
276        printk("\n[ERROR] in %s / thread[%x,%x] cannot allocate buffer for window\n",
277        __FUNCTION__, process->pid, this->trdid );
278        kmem_free( window , bits_log2(sizeof(fbf_window_t)) );
279        vmm_remove_vseg( process , vseg );
280        return -1;
281    }
282 
283    // initialize window descriptor
284    window->pid     = process->pid;
285    window->wid     = wid;
286    window->height  = nlines;
287    window->width   = npixels;
288    window->l_min   = l_min;
289    window->p_min   = p_min;
290    window->hidden  = true;
291    window->buffer  = (uint8_t *)vseg_base;
292
293    // register new window in xlist rooted in FBF extension
294    xlist_add_last( windows_root_xp , XPTR( local_cxy , &window->xlist ) );
295
296    // build extended pointer on relevant entry in windows_tbl[] array
297    xptr_t windows_tbl_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_tbl[wid] );
298
299    // register new window in windows_tbl[] stored in FBF extension
300    hal_remote_s64( windows_tbl_xp , XPTR( local_cxy , window ) );
301
302    // release the lock protecting windows in write mode
303    remote_rwlock_wr_release( windows_lock_xp );
304
305#if DEBUG_DEV_FBF
306cycle = (uint32_t)hal_get_cycles();
307if( DEBUG_DEV_FBF < cycle )
308printk("\n[%s] thread[%x,%x] exit / wid %d / buffer %x / cycle %d\n",
309__FUNCTION__ , this->process->pid, this->trdid, wid , window->buffer, cycle );
310#endif
311
312    // return pointer on allocated buffer
313    *user_buffer = vseg_base;
314
315    return wid;
316
317}  // end dev_fbf_create_window()
318
319/////////////////////////////////////////////
320error_t dev_fbf_active_window( uint32_t  wid,
321                               uint32_t  active )
322{
323
324#if DEBUG_DEV_FBF
325thread_t  * thi   = CURRENT_THREAD;
326uint32_t    cycle = (uint32_t)hal_get_cycles();
327if( DEBUG_DEV_FBF < cycle )
328printk("\n[%s] thread[%x,%x] enters : wid %d / active %d / cycle %d\n",
329__FUNCTION__ , this->process->pid, this->trdid, wid, active, cycle );
330#endif
331
332    // get extended pointer on window to be activated
333    xptr_t window_xp  = dev_fbf_get_xptr_from_wid( wid );
334
335    if( window_xp == XPTR_NULL ) return -1;
336
337    // get cluster and local pointer on target window
338    cxy_t          window_cxy = GET_CXY( window_xp );
339    fbf_window_t * window_ptr = GET_PTR( window_xp );
340
341    // set/reset hidden flag in window descriptor
342    hal_remote_s32( XPTR( window_cxy , &window_ptr->hidden ) , (active == 0) ? 1 : 0 );
343
344#if DEBUG_DEV_FBF
345cycle = (uint32_t)hal_get_cycles();
346if( DEBUG_DEV_FBF < cycle )
347printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
348__FUNCTION__ , this->process->pid, this->trdid, cycle );
349#endif
350
351    return 0;
352
353}  // end dev_fbf_active_window()
354
355////////////////////////////////////////////////////////////////////////////////////////
356// This static function is called by dev_fbf_refresh_window(), dev_fbf_move_window(),
357// dev_fbf_front_window(), dev_fbf_delete_window(), and dev_fbf_resize_window().
358// It updates all lines of a pseudo window identified by the <p_min>, <p_max>, <l_min>,
359// and <l_max> arguments, that are dynamically computed by the caller.
360// This function scan all registered windows to take into account the overlap priorities
361// defined by the FBF xlist of windows. It takes the lock protecting xlist in read mode.
362////////////////////////////////////////////////////////////////////////////////////////
363// Implementation Note:
364// This function contains two loops.
365// - the external loop builds one line of the pseudo window per iteraiion in a local
366//   line_buffer. One line  contains [p_max - p_min] pixels. Then, it calls the FBF
367//   driver (one driver call per line) to write this line into the Frame Buffer.
368// - the internal loop scan the list of the registered windows in increasing priority,
369//   and for each registered window that has a non empty intersection with the handled
370//   line, it updates the line_buffer, using the hal_copy_from_uspace() function
371//   to get the most up-to-date user-defined data.
372////////////////////////////////////////////////////////////////////////////////////////
373// @ p_min   : [in]  upper left corner X coordinate in FBF reference
374// @ p_max   : [in]  upper left corner Y coordinate in FBF reference.
375// @ l_min   : [in]  lower right corner X coordinate in FBF reference (excluded).
376// @ l_max   : [in]  lower right corner Y coordinate in FBF reference (excluded).
377////////////////////////////////////////////////////////////////////////////////////////
378error_t fbf_update( uint32_t    p_min,
379                    uint32_t    l_min,
380                    uint32_t    p_max,
381                    uint32_t    l_max )
382{
383    uint32_t       line;                     // iterator to scan the FBF lines
384    uint32_t       pixel;                    // iterator to scan pixels in one FBF line
385    xptr_t         iter_xp;                  // iterator to scan the list of windows
386    error_t        error;
387
388    // this intermediate buffer to build one pseudo-window line
389    uint8_t  line_buffer[CONFIG_FBF_WINDOWS_MAX_WIDTH];
390
391    // get pointer on calling thread and core lid
392    thread_t  * this = CURRENT_THREAD;
393
394#if DEBUG_DEV_FBF
395uint32_t cycle = (uint32_t)hal_get_cycles();
396if( DEBUG_DEV_FBF < cycle )
397printk("\n[%s] enter : p_min %d / l_min %d / p_max %d / l_max %d / cycle %d\n",
398__FUNCTION__, p_min, l_min, p_max, l_max, cycle );
399#endif
400
401    // get pointers on FBF chdev
402    xptr_t      fbf_xp  = chdev_dir.fbf[0];
403    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
404    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
405
406    // get frame buffer width and height
407    uint32_t fbf_width  = hal_remote_l32( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.width ) );
408    uint32_t fbf_height = hal_remote_l32( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.height ) );
409
410// check arguments
411assert( __FUNCTION__, (p_min < fbf_width)  && (p_max <= fbf_width) && 
412        (l_min < fbf_height) && (l_max <= fbf_height) , "illegal arguments" );
413
414    // get pointer on driver command function
415    dev_cmd_t * cmd = hal_remote_lpt( XPTR( fbf_cxy , &fbf_ptr->cmd ) );
416
417    // build extended pointers on windows xlist root and lock
418    xptr_t  windows_root_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
419    xptr_t  windows_lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
420
421    error = 0;
422
423    // 1. external loop on pseudo window lines (in FBF reference)
424    for( line = l_min ; line < l_max ; line++ )
425    {
426        // reset the line buffer to default value
427        for( pixel = 0 ; pixel < (p_max - p_min) ; pixel++ ) line_buffer[pixel] = 127;
428
429        // take the lock in read mode
430        remote_rwlock_rd_acquire( windows_lock_xp );
431
432        // 2. internal loop on all registered windows
433        XLIST_FOREACH( windows_root_xp , iter_xp )
434        {
435            // get pointers on current target window
436            xptr_t         tgt_xp  = XLIST_ELEMENT( iter_xp , fbf_window_t , xlist );
437            fbf_window_t * tgt_ptr = GET_PTR( tgt_xp );
438            cxy_t          tgt_cxy = GET_CXY( tgt_xp );
439
440            // get target window min and max coordinates in FBF reference
441            bool_t    hidden   = hal_remote_l32( XPTR( tgt_cxy , &tgt_ptr->hidden ) );
442            uint32_t  w_l_min  = hal_remote_l32( XPTR( tgt_cxy , &tgt_ptr->l_min ) );
443            uint32_t  w_p_min  = hal_remote_l32( XPTR( tgt_cxy , &tgt_ptr->p_min ) );
444            uint32_t  w_height = hal_remote_l32( XPTR( tgt_cxy , &tgt_ptr->height ) );
445            uint32_t  w_width  = hal_remote_l32( XPTR( tgt_cxy , &tgt_ptr->width  ) );
446            uint32_t  w_l_max  = w_l_min + w_height;
447            uint32_t  w_p_max  = w_p_min + w_width;
448
449            // does nothing when target window is hidden
450            // or the pseudo window line does not overlap the target window
451            if( (hidden == true)   ||
452                (line  <  w_l_min) ||
453                (line  >= w_l_max) ||
454                (p_max <  w_p_min) ||
455                (p_min >= w_p_max) ) continue;
456
457            // get pointer on buffer associated to target window in user space
458            uint8_t * w_buffer = hal_remote_lpt( XPTR( tgt_cxy , &tgt_ptr->buffer ) ); 
459
460            // get min & max indexes for pixels to be moved in FBF reference
461            uint32_t f_pixel_min = (p_min < w_p_min) ? w_p_min : p_min;
462            uint32_t f_pixel_max = (p_max < w_p_max) ? p_max : w_p_max;
463
464            // compute number of pixels to move from w_buffer to f_buffer
465            uint32_t npixels = f_pixel_max - f_pixel_min;
466
467            // compute offset in line_buffer
468            uint32_t line_offset = f_pixel_min - p_min; 
469
470            // compute line index in window 
471            uint32_t w_line = line - w_l_min;
472
473            // compute offset in window buffer
474            uint32_t w_offset = (w_line * w_height) + f_pixel_min - w_p_min;
475
476            // move pixels from w_buffer (user space) to line_buffer (kernel space)
477            hal_copy_from_uspace( XPTR( local_cxy  , &line_buffer[line_offset] ),
478                                  &w_buffer[w_offset], 
479                                  npixels );
480        }  // end for windows
481
482        // release the lock
483        remote_rwlock_rd_release( windows_lock_xp );
484
485        // compute offset in FBF
486        uint32_t fbf_offset = p_min + (line * fbf_width);
487
488        // register command in calling thread descriptor
489        this->fbf_cmd.dev_xp    = fbf_xp;
490        this->fbf_cmd.type      = FBF_DRIVER_KERNEL_WRITE;
491        this->fbf_cmd.buffer    = line_buffer;
492        this->fbf_cmd.npixels   = p_max - p_min;
493        this->fbf_cmd.offset    = fbf_offset;
494
495        // call driver to display one line
496        cmd( XPTR( local_cxy , this ) );
497
498        error |= this->fbf_cmd.error;
499   
500    }  // end for lines
501
502#if DEBUG_DEV_FBF
503cycle = (uint32_t)hal_get_cycles();
504if( DEBUG_DEV_FBF < cycle )
505printk("\n[%s] exit / cycle %d\n",
506__FUNCTION__, cycle );
507#endif
508
509    // return I/O operation status
510    return error;
511
512}  // end fbf_update()
513
514//////////////////////////////////////////////
515error_t dev_fbf_delete_window( uint32_t  wid )
516{
517    thread_t  * this    = CURRENT_THREAD;
518    process_t * process = this->process;
519
520#if DEBUG_DEV_FBF
521uint32_t   cycle = (uint32_t)hal_get_cycles();
522if( DEBUG_DEV_FBF < cycle )
523printk("\n[%s] thread[%x,%x] enters : wid %d / cycle %d\n",
524__FUNCTION__ , process->pid, this->trdid, wid, cycle );
525#endif
526
527    // get extended pointer on window to be deleted
528    xptr_t window_xp  = dev_fbf_get_xptr_from_wid( wid );
529
530    if( window_xp == XPTR_NULL ) return -1;
531
532    // get cluster and pointers on FBF chdev
533    xptr_t      fbf_xp  = chdev_dir.fbf[0];
534    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
535    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
536
537    // build extended pointers on windows lock, windows_tbl[wid] and wid allocator
538    xptr_t windows_lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
539    xptr_t wid_bitmap_xp   = XPTR( fbf_cxy ,  fbf_ptr->ext.fbf.windows_bitmap );
540    xptr_t windows_tbl_xp  = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_tbl[wid] );
541
542    // get cluster and local pointer on window
543    cxy_t          window_cxy = GET_CXY( window_xp );
544    fbf_window_t * window_ptr = GET_PTR( window_xp );
545
546    // get relevant info from window descriptor
547    uint32_t   p_min   = hal_remote_l32( XPTR( window_cxy , &window_ptr->p_min ) );
548    uint32_t   l_min   = hal_remote_l32( XPTR( window_cxy , &window_ptr->l_min ) );
549    uint32_t   npixels = hal_remote_l32( XPTR( window_cxy , &window_ptr->width ) );
550    uint32_t   nlines  = hal_remote_l32( XPTR( window_cxy , &window_ptr->height ) );
551    uint8_t  * buffer  = hal_remote_lpt( XPTR( window_cxy , &window_ptr->buffer ) );
552
553    // 1. set the hidden bit in window descriptor
554    hal_remote_s32( XPTR( window_cxy , &window_ptr->hidden ) , true );
555
556    // 2. refresh the window in FBF
557    fbf_update( p_min, l_min, p_min + npixels, l_min + nlines );
558
559    // 3. take the lock protecting windows in write mode
560    remote_rwlock_wr_acquire( windows_lock_xp );
561
562    // 4. remove the window from windows_tbl[] array
563    hal_remote_s64( windows_tbl_xp , XPTR_NULL );
564
565    // 5. remove the window from xlist     
566    xlist_unlink( XPTR( window_cxy , &window_ptr->xlist ) );
567
568    // 6. release wid to bitmap
569    bitmap_remote_clear( wid_bitmap_xp , wid );
570
571    // 7. release the lock protecting windows in write mode
572    remote_rwlock_wr_release( windows_lock_xp );
573 
574    // 8. release memory allocated for window descriptor
575    kmem_remote_free( window_cxy , window_ptr , bits_log2(sizeof(fbf_window_t)) );
576
577    // 9. release the associated vseg
578    vmm_global_delete_vseg( process , (intptr_t)buffer );
579   
580#if DEBUG_DEV_FBF
581cycle = (uint32_t)hal_get_cycles();
582if( DEBUG_DEV_FBF < cycle )
583printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
584__FUNCTION__ , process->pid, this->trdid, cycle );
585#endif
586
587    return 0;
588
589}  // end dev_fbf_delete_window()
590
591////////////////////////////////////////////
592error_t dev_fbf_move_window( uint32_t  wid,
593                             uint32_t  l_new,
594                             uint32_t  p_new )
595{
596
597#if DEBUG_DEV_FBF
598thread_t  * this  = CURRENT_THREAD;
599uint32_t    cycle = (uint32_t)hal_get_cycles();
600if( DEBUG_DEV_FBF < cycle )
601printk("\n[%s] thread[%x,%x] enters : wid %d / l_new %d / p_new %d / cycle %d\n",
602__FUNCTION__ , this->process->pid, this->trdid, wid, l_new, p_new, cycle );
603#endif
604
605    // get extended pointer on window to be moved
606    xptr_t window_xp  = dev_fbf_get_xptr_from_wid( wid );
607
608    if( window_xp == XPTR_NULL ) return -1;
609
610    // get cluster and pointers on FBF chdev
611    xptr_t      fbf_xp  = chdev_dir.fbf[0];
612    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
613    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
614
615    // build extended pointers on windows lock and root
616    xptr_t windows_lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
617    xptr_t windows_root_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
618
619
620    // get cluster and local pointer on target window
621    cxy_t          window_cxy = GET_CXY( window_xp );
622    fbf_window_t * window_ptr = GET_PTR( window_xp );
623
624    // get target window coordinates, width and height
625    uint32_t p_old     = hal_remote_l32( XPTR( window_cxy , &window_ptr->p_min ) );
626    uint32_t l_old     = hal_remote_l32( XPTR( window_cxy , &window_ptr->l_min ) );
627    uint32_t nlines    = hal_remote_l32( XPTR( window_cxy , &window_ptr->height ) );
628    uint32_t npixels   = hal_remote_l32( XPTR( window_cxy , &window_ptr->width ) );
629
630    // build extended pointer on window xlist_entry
631    xptr_t xlist_entry_xp =  XPTR( window_cxy , &window_ptr->xlist );
632
633    // does nothing if no change
634    if( (p_new == p_old) && (l_new == l_old) )  return 0;
635
636    // 1. set the "hidden" flag in window descriptor
637    hal_remote_s32( XPTR( window_cxy , &window_ptr->hidden ) , true );
638
639#if ( DEBUG_DEV_FBF & 1 )
640printk("\n[%s] hidden set\n", __FUNCTION__ );
641#endif
642
643    // 2. update the FBF for the old window position
644    fbf_update( p_old , l_old , p_old + npixels, l_old + nlines );
645
646#if ( DEBUG_DEV_FBF & 1 )
647printk("\n[%s] refreshed old window\n", __FUNCTION__ );
648#endif
649
650    // 3. take the lock protecting windows in write mode
651    remote_rwlock_wr_acquire( windows_lock_xp );
652
653#if ( DEBUG_DEV_FBF & 1 )
654printk("\n[%s] lock taken\n", __FUNCTION__ );
655#endif
656
657    // 4. set the new coordinates in the window descriptor,
658    hal_remote_s32( XPTR( window_cxy , &window_ptr->l_min ), l_new );
659    hal_remote_s32( XPTR( window_cxy , &window_ptr->p_min ), p_new );
660
661#if ( DEBUG_DEV_FBF & 1 )
662printk("\n[%s] l_min & p_min updated\n", __FUNCTION__ );
663#endif
664
665    // 5. gives the window the highest priority
666    xlist_unlink( xlist_entry_xp );
667    xlist_add_last( windows_root_xp , xlist_entry_xp );
668
669#if ( DEBUG_DEV_FBF & 1 )
670printk("\n[%s] set high priority\n", __FUNCTION__ );
671#endif
672
673    // 6. release the lock protecting windows in write mode
674    remote_rwlock_wr_release( windows_lock_xp );
675 
676#if ( DEBUG_DEV_FBF & 1 )
677printk("\n[%s] lock released\n", __FUNCTION__ );
678#endif
679
680    // 7. reset the "hidden" flag in window descriptor
681    hal_remote_s32( XPTR( window_cxy , &window_ptr->hidden ) , false );
682
683#if ( DEBUG_DEV_FBF & 1 )
684printk("\n[%s] hidden reset\n", __FUNCTION__ );
685#endif
686
687    // 8. update the FBF for the new window position
688    fbf_update( p_new , l_new , p_new + npixels, l_new + nlines );
689
690#if ( DEBUG_DEV_FBF & 1 )
691printk("\n[%s] refresh new new window\n", __FUNCTION__ );
692#endif
693
694#if DEBUG_DEV_FBF
695cycle = (uint32_t)hal_get_cycles();
696if( DEBUG_DEV_FBF < cycle )
697printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
698__FUNCTION__ , this->process->pid, this->trdid, cycle );
699#endif
700
701    return 0;
702
703}  // end dev_fbf_move_window()
704
705/////////////////////////////////////////////
706error_t dev_fbf_resize_window( uint32_t  wid,
707                               uint32_t  width,
708                               uint32_t  height )
709{
710    thread_t  * this    = CURRENT_THREAD;
711    process_t * process = this->process;
712
713#if DEBUG_DEV_FBF
714uint32_t    cycle = (uint32_t)hal_get_cycles();
715if( DEBUG_DEV_FBF < cycle )
716printk("\n[%s] thread[%x,%x] enters : wid %d / width %d / height %d / cycle %d\n",
717__FUNCTION__ , process->pid , this->trdid , wid, width , height , cycle );
718#endif
719
720    // get extended pointer on window to be resized
721    xptr_t window_xp  = dev_fbf_get_xptr_from_wid( wid );
722
723    if( window_xp == XPTR_NULL ) return -1;
724
725    // get cluster and pointers on FBF chdev
726    xptr_t      fbf_xp  = chdev_dir.fbf[0];
727    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
728    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
729
730    // build extended pointers on windows lock and root
731    xptr_t windows_lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
732    xptr_t windows_root_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
733
734    // get cluster and local pointer on target window
735    cxy_t          window_cxy = GET_CXY( window_xp );
736    fbf_window_t * window_ptr = GET_PTR( window_xp );
737
738    // get process owner PID, width, height, and buffer
739    uint32_t p_min   = hal_remote_l32( XPTR( window_cxy , &window_ptr->p_min ) );
740    uint32_t l_min   = hal_remote_l32( XPTR( window_cxy , &window_ptr->l_min ) );
741    uint32_t nlines  = hal_remote_l32( XPTR( window_cxy , &window_ptr->height ) );
742    uint32_t npixels = hal_remote_l32( XPTR( window_cxy , &window_ptr->width ) );
743    void   * base    = hal_remote_lpt( XPTR( window_cxy , &window_ptr->buffer ) );
744
745    // build extended pointer on window xlist_entry
746    xptr_t xlist_entry_xp =  XPTR( window_cxy , &window_ptr->xlist );
747
748    // does nothing if no change
749    if( (width == npixels) && (height == nlines) ) return 0;
750
751    // compute old_size and new size
752    uint32_t old_size = nlines * npixels;
753    uint32_t new_size = width * height;
754
755    // 1. set the "hidden" flag in window descriptor
756    hal_remote_s32( XPTR( window_cxy , &window_ptr->hidden ) , true );
757
758#if ( DEBUG_DEV_FBF & 1 )
759printk("\n[%s] hidden set\n", __FUNCTION__ );
760#endif
761
762    // 2. refresh the FBF for the current window size
763    fbf_update( p_min , l_min , p_min + npixels, l_min + nlines );
764
765#if ( DEBUG_DEV_FBF & 1 )
766printk("\n[%s] refreshed old window\n", __FUNCTION__ );
767#endif
768
769    // 3. take the lock protecting windows in write mode
770    remote_rwlock_wr_acquire( windows_lock_xp );
771
772#if ( DEBUG_DEV_FBF & 1 )
773printk("\n[%s] lock taken\n", __FUNCTION__ );
774#endif
775
776    // 4. set the new width & height in the window descriptor,
777    hal_remote_s32( XPTR( window_cxy , &window_ptr->width  ), width );
778    hal_remote_s32( XPTR( window_cxy , &window_ptr->height ), height );
779
780#if ( DEBUG_DEV_FBF & 1 )
781printk("\n[%s] width & height updated\n", __FUNCTION__ );
782#endif
783
784    // 5. resize vseg if required
785    vmm_global_resize_vseg( process, (intptr_t)base, (intptr_t)base, width * height );
786
787#if ( DEBUG_DEV_FBF & 1 )
788printk("\n[%s] vseg resized\n", __FUNCTION__ );
789#endif
790
791    // 6. fill buffer extension if required
792    if( new_size > old_size )  memset( base + old_size , 0 , new_size - old_size );
793
794#if ( DEBUG_DEV_FBF & 1 )
795printk("\n[%s] buffer extension initialized\n", __FUNCTION__ );
796#endif
797
798    // 7. gives the window the highest priority
799    xlist_unlink( xlist_entry_xp );
800    xlist_add_last( windows_root_xp , xlist_entry_xp );
801
802#if ( DEBUG_DEV_FBF & 1 )
803printk("\n[%s] set high priority\n", __FUNCTION__ );
804#endif
805
806    // 8. release the lock protecting windows in write mode
807    remote_rwlock_wr_release( windows_lock_xp );
808 
809#if ( DEBUG_DEV_FBF & 1 )
810printk("\n[%s] lock released\n", __FUNCTION__ );
811#endif
812
813    // 9. reset the "hidden" flag in window descriptor
814    hal_remote_s32( XPTR( window_cxy , &window_ptr->hidden ) , false );
815
816#if ( DEBUG_DEV_FBF & 1 )
817printk("\n[%s] hidden reset\n", __FUNCTION__ );
818#endif
819
820    // 10. refresh the FBF for the new window position
821    fbf_update( p_min , l_min , p_min + width, l_min + height );
822
823#if ( DEBUG_DEV_FBF & 1 )
824printk("\n[%s] refreshed new window\n", __FUNCTION__ );
825#endif
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_min,
841                                uint32_t  line_max )
842{
843
844#if DEBUG_DEV_FBF
845thread_t  * thi   = CURRENT_THREAD;
846uint32_t    cycle = (uint32_t)hal_get_cycles();
847if( DEBUG_DEV_FBF < cycle )
848printk("\n[%s] thread[%x,%x] enters for wid %d / first %d / last %d / cycle %d\n",
849__FUNCTION__ , this->process->pid, this->trdid, wid, line_min, line_max, cycle );
850#endif
851
852    // get extended pointer on window to be refreshed
853    xptr_t window_xp  = dev_fbf_get_xptr_from_wid( wid );
854
855    if( window_xp == XPTR_NULL ) return -1;
856
857    // get cluster and local pointer on target window
858    cxy_t          window_cxy = GET_CXY( window_xp );
859    fbf_window_t * window_ptr = GET_PTR( window_xp );
860
861    // get p_min, l_min, nlines  & npixels from window descriptor
862    uint32_t p_min   = hal_remote_l32( XPTR( window_cxy , &window_ptr->p_min ) ); 
863    uint32_t l_min   = hal_remote_l32( XPTR( window_cxy , &window_ptr->l_min ) ); 
864    uint32_t npixels = hal_remote_l32( XPTR( window_cxy , &window_ptr->width ) ); 
865    uint32_t nlines  = hal_remote_l32( XPTR( window_cxy , &window_ptr->height ) ); 
866
867    // check <line_min> and <line_max> arguments
868    if( (line_min >= nlines) || (line_max > nlines) || (line_min >= line_max) )
869    {
870        printk("\n[ERROR] in %s : illegal arguments / l_first %d / l_last %d / nlines %d\n",
871        __FUNCTION__, line_min, line_max, nlines );
872        return -1;
873    }
874
875    // update FBF
876    fbf_update( p_min , l_min + line_min , p_min + npixels , l_min + line_max );
877
878#if DEBUG_DEV_FBF
879cycle = (uint32_t)hal_get_cycles();
880if( DEBUG_DEV_FBF < cycle )
881printk("\n[%s] thread[%x,%x] exit for wid %d / cycle %d\n",
882__FUNCTION__, this->process->pid, this->trdid, wid, cycle );
883#endif
884
885    return 0;
886
887}  // end dev_fbf_refresh_window()
888
889////////////////////////////////////////////
890error_t dev_fbf_front_window( uint32_t wid )
891{
892
893#if DEBUG_DEV_FBF
894thread_t  * this  = CURRENT_THREAD;
895uint32_t    cycle = (uint32_t)hal_get_cycles();
896if( DEBUG_DEV_FBF < cycle )
897printk("\n[%s] thread[%x,%x] enters for wid %d / cycle %d\n",
898__FUNCTION__ , this->process->pid, this->trdid, wid, cycle );
899#endif
900
901    // get extended pointer on window to be refreshed
902    xptr_t window_xp  = dev_fbf_get_xptr_from_wid( wid );
903
904    if( window_xp == XPTR_NULL ) return -1;
905
906    // get cluster and pointers on FBF chdev
907    xptr_t      fbf_xp  = chdev_dir.fbf[0];
908    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
909    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
910
911    // build extended pointer on windows lock and root
912    xptr_t  windows_lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
913    xptr_t  windows_root_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
914
915    // get cluster and local pointers on window
916    cxy_t          window_cxy = GET_CXY( window_xp );
917    fbf_window_t * window_ptr = GET_PTR( window_xp );
918
919    // get target window coordinates, width, height, and hidden
920    uint32_t p_min     = hal_remote_l32( XPTR( window_cxy , &window_ptr->p_min ) );
921    uint32_t l_min     = hal_remote_l32( XPTR( window_cxy , &window_ptr->l_min ) );
922    uint32_t nlines    = hal_remote_l32( XPTR( window_cxy , &window_ptr->height ) );
923    uint32_t npixels   = hal_remote_l32( XPTR( window_cxy , &window_ptr->width ) );
924    bool_t   hidden    = hal_remote_l32( XPTR( window_cxy , &window_ptr->hidden ) );
925
926    // build extended pointer on window xlist_entry
927    xptr_t xlist_entry_xp =  XPTR( window_cxy , &window_ptr->xlist );
928
929    // 1. take the lock protecting windows in write mode
930    remote_rwlock_wr_acquire( windows_lock_xp );
931
932#if ( DEBUG_DEV_FBF & 1 )
933printk("\n[%s] lock taken\n", __FUNCTION__ );
934#endif
935
936    // 2. gives the window the highest priority
937    xlist_unlink( xlist_entry_xp );
938    xlist_add_last( windows_root_xp , xlist_entry_xp );
939
940#if ( DEBUG_DEV_FBF & 1 )
941printk("\n[%s] set high priority \n", __FUNCTION__ );
942#endif
943
944    // 3. release the lock protecting windows from write mode
945    remote_rwlock_wr_release( windows_lock_xp );
946 
947#if ( DEBUG_DEV_FBF & 1 )
948printk("\n[%s] lock released\n", __FUNCTION__ );
949#endif
950
951    // 4. update the FBF for this window when not hidden
952    if( hidden == false ) fbf_update( p_min , l_min , p_min + npixels, l_min + nlines );
953
954#if ( DEBUG_DEV_FBF & 1 )
955printk("\n[%s] refresh window in FBF\n", __FUNCTION__ );
956#endif
957
958#if DEBUG_DEV_FBF
959cycle = (uint32_t)hal_get_cycles();
960if( DEBUG_DEV_FBF < cycle )
961printk("\n[%s] thread[%x,%x] exit for wid %d / cycle %d\n",
962__FUNCTION__ , this->process->pid, this->trdid, wid, cycle );
963#endif
964
965    return 0;
966
967}   // end dev_fbf_front_window()
968
969/////////////////////////////////////////
970void dev_fbf_display_windows( pid_t pid )
971{
972    xptr_t  iter_xp;
973
974    // display header
975    printk("\n***** registered FBF windows *****\n"
976           "   wid   | hide  | lzero | pzero | lines | pixel | pid\n" );
977
978    // get cluster and pointers on FBF chdev
979    xptr_t      fbf_xp  = chdev_dir.fbf[0];
980    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
981    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
982
983    // build extended pointer on windows lock and root
984    xptr_t  lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
985    xptr_t  root_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
986
987    // take the lock in read mode
988    remote_rwlock_rd_acquire( lock_xp );
989
990    XLIST_FOREACH_BACKWARD( root_xp , iter_xp )
991    {
992        xptr_t         w_xp  = XLIST_ELEMENT( iter_xp , fbf_window_t , xlist );
993        fbf_window_t * w_ptr = GET_PTR( w_xp );
994        cxy_t          w_cxy = GET_CXY( w_xp );
995
996        uint32_t wid       = hal_remote_l32( XPTR( w_cxy , &w_ptr->wid   ) );
997        uint32_t owner_pid = hal_remote_l32( XPTR( w_cxy , &w_ptr->pid   ) );
998        uint32_t hide      = hal_remote_l32( XPTR( w_cxy , &w_ptr->hidden ) );
999        uint32_t lzero     = hal_remote_l32( XPTR( w_cxy , &w_ptr->l_min ) );
1000        uint32_t pzero     = hal_remote_l32( XPTR( w_cxy , &w_ptr->p_min ) );
1001        uint32_t lines     = hal_remote_l32( XPTR( w_cxy , &w_ptr->height ) );
1002        uint32_t pixels    = hal_remote_l32( XPTR( w_cxy , &w_ptr->width ) );
1003
1004        if( (pid == 0) || (pid == owner_pid) )
1005        { 
1006            printk("%d\t | %d\t | %d\t | %d\t | %d\t | %d\t | %x\n",
1007                    wid,   hide,  lzero, pzero, lines, pixels, pid );
1008        }
1009    }
1010
1011    // release the lock
1012    remote_rwlock_rd_release( lock_xp );
1013
1014}  // end dev_fbf_display_windows()
1015
1016/////////////////////////////////
1017void dev_fbf_cleanup( pid_t pid )
1018{
1019    xptr_t  iter_xp;
1020
1021    // get cluster and pointers on FBF chdev
1022    xptr_t      fbf_xp  = chdev_dir.fbf[0];
1023    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
1024    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
1025
1026    // build extended pointer on windows lock and root
1027    xptr_t  lock_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_lock );
1028    xptr_t  root_xp = XPTR( fbf_cxy , &fbf_ptr->ext.fbf.windows_root );
1029
1030    // take the lock in read mode
1031    remote_rwlock_rd_acquire( lock_xp );
1032
1033    XLIST_FOREACH( root_xp , iter_xp )
1034    {
1035        xptr_t         w_xp  = XLIST_ELEMENT( iter_xp , fbf_window_t , xlist );
1036        fbf_window_t * w_ptr = GET_PTR( w_xp );
1037        cxy_t          w_cxy = GET_CXY( w_xp );
1038
1039        // get owner process PID and WID
1040        uint32_t   owner_pid  = hal_remote_l32( XPTR( w_cxy , &w_ptr->pid ) );
1041        uint32_t   wid        = hal_remote_l32( XPTR( w_cxy , &w_ptr->wid ) );
1042
1043        // delete matching window
1044        if( pid == owner_pid ) dev_fbf_delete_window( wid );
1045    }
1046
1047    // release the lock from read mode
1048    remote_rwlock_rd_release( lock_xp );
1049
1050}  // end dev_fbf_cleanup()
1051
1052
1053
1054
1055///////////////////////////////////////////////
1056// TODO Deprecated : january 2020 [AG]
1057///////////////////////////////////////////////
1058error_t dev_fbf_move_data( bool_t     is_write,
1059                           void     * user_buffer,
1060                           uint32_t   npixels,
1061                           uint32_t   offset )
1062{
1063    // get pointer on calling thread
1064    thread_t * this = CURRENT_THREAD;
1065
1066#if DEBUG_DEV_FBF
1067uint32_t   cycle = (uint32_t)hal_get_cycles();
1068if( DEBUG_DEV_FBF < cycle )
1069printk("\n[%s] thread[%x,%x] :  buffer %x / npixels %d / offset %x / cycle %d\n",
1070__FUNCTION__ , this->process->pid, this->trdid, 
1071user_buffer, npixels, offset, cycle );
1072#endif
1073
1074    // get pointers on FBF chdev
1075    xptr_t      fbf_xp  = chdev_dir.fbf[0];
1076    cxy_t       fbf_cxy = GET_CXY( fbf_xp );
1077    chdev_t   * fbf_ptr = GET_PTR( fbf_xp );
1078
1079    // get frame buffer width and height
1080    uint32_t width  = hal_remote_l32 ( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.width ) );
1081    uint32_t height = hal_remote_l32 ( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.height ) );
1082
1083    // check offset and npixels versus FBF size
1084    if( ((offset + npixels) > (width * height)) )
1085    {
1086        printk("\n[ERROR] in %s : offset (%d) + npixels (%d) / width (%d) / height (%d)\n",
1087        __FUNCTION__, offset, npixels, width, height ); 
1088        return -1;
1089    }
1090
1091    // register command in calling thread descriptor
1092    this->fbf_cmd.dev_xp    = fbf_xp;
1093    this->fbf_cmd.type      = is_write ? FBF_DRIVER_USER_WRITE : FBF_DRIVER_USER_READ;
1094    this->fbf_cmd.buffer    = user_buffer;
1095    this->fbf_cmd.offset    = offset;
1096    this->fbf_cmd.npixels   = npixels;
1097
1098    // get driver command function
1099    dev_cmd_t * cmd = (dev_cmd_t *)hal_remote_lpt( XPTR( fbf_cxy , &fbf_ptr->cmd ) );
1100
1101    // call driver
1102    cmd( XPTR( local_cxy , this ) );
1103
1104    error_t error = this->fbf_cmd.error;
1105
1106#if DEBUG_DEV_FBF
1107cycle = (uint32_t)hal_get_cycles();
1108if( DEBUG_DEV_FBF < cycle )
1109printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
1110__FUNCTION__ , this->process->pid, this->trdid, cycle );
1111#endif
1112
1113    // return I/O operation status
1114    return error;
1115
1116}  // end dev_fbf_move_data()
1117
1118
Note: See TracBrowser for help on using the repository browser.