/* * soclib_fbf.c - soclib frame-buffer driver implementation. * * Author Alain greiner (2016,2017,2018,2019) * * 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 cmd_type; // READ / WRITE / SYNC_READ / SYNC_WRITE uint32_t offset; uint32_t length; void * buffer; // pointer on memory buffer in user space xptr_t fbf_xp; uint32_t status; // I/0 operation status (from BDV) // 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(); thread_t * this = CURRENT_THREAD; 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 cmd_type = hal_remote_l32( XPTR( th_cxy , &th_ptr->fbf_cmd.type ) ); offset = hal_remote_l32( XPTR( th_cxy , &th_ptr->fbf_cmd.offset ) ); length = hal_remote_l32( XPTR( th_cxy , &th_ptr->fbf_cmd.length ) ); buffer = hal_remote_lpt( XPTR( th_cxy , &th_ptr->fbf_cmd.buffer ) ); fbf_xp = (xptr_t)hal_remote_l64( XPTR( th_cxy , &th_ptr->fbf_cmd.dev_xp ) ); // 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( cmd_type == FBF_READ ) // use a (kernel -> user) memcpy { #if DEBUG_HAL_FBF if( DEBUG_HAL_FBF < cycle ) printk("\n[%s] thread[%x,%x] / client[%x,%x] / READ / offset / length / buffer %x / cycle %d\n", __FUNCTION__ , this->process->pid, this->trdid, client_pid, client_trdid, offset, length, buffer, cycle ); #endif hal_copy_to_uspace( buffer, base_xp + offset, length ); } else // cmd_type == FBF_WRITE => use a (user -> kernel) memcpy { #if DEBUG_HAL_FBF if( DEBUG_HAL_FBF < cycle ) printk("\n[%s] thread[%x,%x] / client[%x,%x] / WRITE / offset / length / buffer %x / cycle %d\n", __FUNCTION__ , this->process->pid, this->trdid, client_pid, client_trdid, offset, length, buffer, cycle ); #endif hal_copy_from_uspace( base_xp + offset, buffer, length ); } // set success in command hal_remote_s32( XPTR( th_cxy , &th_ptr->fbf_cmd.error ) , 0 ); } // end soclib_fbf_cmd()