/* * soclib_fbf.c - soclib frame-buffer driver implementation. * * Author Alain greiner (2016,2017,2018,2019,2020) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH.. * * ALMOS-MKH. is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH. is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH.; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include /////////////////////////////////////// void soclib_fbf_init( chdev_t * chdev ) { // set driver specific fields in FBF chdev chdev->cmd = &soclib_fbf_cmd; chdev->isr = NULL; // get extended pointer on SOCLIB_FBF peripheral segment base xptr_t base_xp = chdev->base; // get cluster and local pointer for the SOCLIB_FBF peripheral segment cxy_t base_cxy = GET_CXY( base_xp ); uint32_t * base_ptr = GET_PTR( base_xp ); // get frame buffer width, height, and type uint32_t width = hal_remote_l32( XPTR( base_cxy , base_ptr + FBF_WIDTH_REG ) ); uint32_t height = hal_remote_l32( XPTR( base_cxy , base_ptr + FBF_HEIGHT_REG ) ); uint32_t type = hal_remote_l32( XPTR( base_cxy , base_ptr + FBF_SUBSAMPLING_REG ) ); // set FBF chdev extension fields chdev->ext.fbf.width = width; chdev->ext.fbf.height = height; chdev->ext.fbf.subsampling = type; } // end soclib_fbf_init() ///////////////////////////////////////////////////////////////// void __attribute__((noinline)) soclib_fbf_cmd( xptr_t thread_xp ) { uint32_t type; // USER_WRITE / USER_READ / KERNEL_WRITE / KERNEL_READ uint32_t offset; // offset in FBF (in pixels) uint32_t npixels; // number of pixels to move xptr_t fbf_xp; // extended pointer on FBF chdev descriptor void * buffer; // pointer on kernel or user buffer // get client thread cluster and local pointer cxy_t th_cxy = GET_CXY( thread_xp ); thread_t * th_ptr = GET_PTR( thread_xp ); #if (DEBUG_HAL_FBF|| DEBUG_HAL_FBF) uint32_t cycle = (uint32_t)hal_get_cycles(); process_t * process = hal_remote_lpt( XPTR( th_cxy , &th_ptr->process ) ); pid_t client_pid = hal_remote_l32( XPTR( th_cxy , &process->pid ) ); trdid_t client_trdid = hal_remote_l32( XPTR( th_cxy , &th_ptr->trdid ) ); #endif // get command arguments type = hal_remote_l32( XPTR( th_cxy , &th_ptr->fbf_cmd.type ) ); offset = hal_remote_l32( XPTR( th_cxy , &th_ptr->fbf_cmd.offset ) ); npixels = hal_remote_l32( XPTR( th_cxy , &th_ptr->fbf_cmd.npixels ) ); fbf_xp = hal_remote_l64( XPTR( th_cxy , &th_ptr->fbf_cmd.dev_xp ) ); buffer = hal_remote_lpt( XPTR( th_cxy , &th_ptr->fbf_cmd.buffer ) ); // get cluster and local pointer on FBF chdev cxy_t fbf_cxy = GET_CXY( fbf_xp ); chdev_t * fbf_ptr = GET_PTR( fbf_xp ); // get extended pointer on SOCLIB_FBF peripheral segment base xptr_t base_xp = (xptr_t)hal_remote_l64( XPTR( fbf_cxy , &fbf_ptr->base ) ); // execute command if( type == FBF_DRIVER_USER_WRITE ) // user_buffer => FBF { #if DEBUG_HAL_FBF if( DEBUG_HAL_FBF < cycle ) printk("\n[%s] client thread[%x,%x] / USER_WRITE / offset %d / npixels %d / buf %x\n", __FUNCTION__ , client_pid, client_trdid, offset, npixels, buffer ); #endif hal_copy_from_uspace( base_xp + offset, buffer, npixels ); } else if( type == FBF_DRIVER_USER_READ ) // FBF => user_buffer { #if DEBUG_HAL_FBF if( DEBUG_HAL_FBF < cycle ) printk("\n[%s] client thread[%x,%x] / USER_READ / offset %d / npixels %d / buf %x\n", __FUNCTION__ , client_pid, client_trdid, offset, npixels, buffer ); #endif hal_copy_to_uspace( buffer, base_xp + offset, npixels ); } else if( type == FBF_DRIVER_KERNEL_WRITE ) // kernel_buffer => FBF { #if DEBUG_HAL_FBF if( DEBUG_HAL_FBF < cycle ) printk("\n[%s] client thread[%x,%x] / KERNEL_WRITE / offset %d / npixels %d / buf %x\n", __FUNCTION__ , client_pid, client_trdid, offset, npixels, buffer ); #endif hal_remote_memcpy( base_xp + offset, XPTR( local_cxy , buffer ), npixels ); } else if( type == FBF_DRIVER_KERNEL_READ ) // FBF => kernel_buffer { #if DEBUG_HAL_FBF if( DEBUG_HAL_FBF < cycle ) printk("\n[%s] client thread[%x,%x] / KERNEL_READ / offset %d / npixels %d / buf %x\n", __FUNCTION__ , client_pid, client_trdid, offset, npixels, buffer ); #endif hal_remote_memcpy( XPTR( local_cxy , buffer ), base_xp + offset, npixels ); } // set success in command hal_remote_s32( XPTR( th_cxy , &th_ptr->fbf_cmd.error ) , 0 ); #if DEBUG_HAL_FBF if( DEBUG_HAL_FBF < cycle ) printk("\n[%s] client thread[%x,%x] / successful move / cycle %d\n", __FUNCTION__ , client_pid, client_trdid , cycle ); #endif } // end soclib_fbf_cmd()