/* * dev_fbf.c - FBF (Block Device Controler) generic device API implementation. * * Author Alain Greiner (2016,2017,2018) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MK * * 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-kernel; 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 #include ///////////////////////////////////////////////////////////////////////////////////////// // Extern global variables ///////////////////////////////////////////////////////////////////////////////////////// extern chdev_directory_t chdev_dir; // allocated in kernel_init.c //////////////////////////////////// void dev_fbf_init( chdev_t * chdev ) { // set FBF chdev extension fields // TODO this should be done in the implementation // TODO specific part, as these parameters must be obtained from the hardware. chdev->ext.fbf.width = CONFIG_FBF_WIDTH; chdev->ext.fbf.height = CONFIG_FBF_HEIGHT; // get implementation uint32_t impl = chdev->impl; // set chdev name strcpy( chdev->name, "fbf" ); // call driver init function if( impl == IMPL_FBF_SCL ) { printk("\n[WARNING] Soclib FBF driver not implemented yet\n"); } else { assert( false , "undefined FBF device implementation" ); } } // end dev_fbf_init() ///////////////////////////////////////// void dev_fbf_get_size( uint32_t * width, uint32_t * height ) { // get extended pointer on FBF chdev descriptor xptr_t dev_xp = chdev_dir.fbf[0]; assert( (dev_xp != XPTR_NULL) , "undefined FBF chdev descriptor" ); // get FBF chdev cluster and local pointer cxy_t dev_cxy = GET_CXY( dev_xp ); chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); // return values *width = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.width ) ); *height = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.height ) ); } // end dev_fbf_get_size() ///////////////////////////// error_t dev_fbf_alloc( void ) { // get extended pointer on FBF chdev descriptor // xptr_t dev_xp = chdev_dir.fbf[0]; // assert( (dev_xp != XPTR_NULL) , "undefined FBF chdev descriptor" ); // get FBF chdev cluster and local pointer // cxy_t dev_cxy = GET_CXY( dev_xp ); // chdev_t * dev_ptr = GET_PTR( dev_xp ); // try to get FBF ownership assert( false , "not implemented yet" ); } // end dev_fbf_alloc() ///////////////////////// void dev_fbf_free( void ) { // get extended pointer on FBF chdev descriptor // xptr_t dev_xp = chdev_dir.fbf[0]; // assert( (dev_xp != XPTR_NULL) , "undefined FBF chdev descriptor" ); // get FBF chdev cluster and local pointer // cxy_t dev_cxy = GET_CXY( dev_xp ); // chdev_t * dev_ptr = (GET_PTR( dev_xp ); // release FBF ownership assert( false , "not implemented yet" ); } // end dev_fbf_free() ////////////////////////////////////////////////////////////////////////////////// // This static function is called by dev_fbf_read() & dev_fbf_write() functions. // It builds and registers the command in the calling thread descriptor. // Then, it registers the calling thread in the relevant DMA chdev waiting queue. // Finally it blocks on the THREAD_BLOCKED_DEV condition and deschedule. ////////////////////////////////////i///////////////////////////////////////////// static error_t dev_fbf_access( bool_t to_fbf, char * buffer, uint32_t length, uint32_t offset ) { // get extended pointer on FBF chdev descriptor xptr_t fbf_xp = chdev_dir.fbf[0]; assert( (fbf_xp != XPTR_NULL) , "undefined FBF chdev descriptor" ); // get FBF chdev cluster and local pointer cxy_t fbf_cxy = GET_CXY( fbf_xp ); chdev_t * fbf_ptr = (chdev_t *)GET_PTR( fbf_xp ); // get frame buffer base address, width and height xptr_t base = hal_remote_l64( XPTR( fbf_cxy , &fbf_ptr->base ) ); uint32_t width = hal_remote_l32 ( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.width ) ); uint32_t height = hal_remote_l32 ( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.height ) ); // check offset and length versus FBF size assert( ((offset + length) <= (width * height)) , "offset %d / length %d / width %d / height %d\n", offset, length, width, height ); // compute extended pointers on frame buffer and memory buffer xptr_t mem_buf_xp = XPTR( local_cxy , buffer ); xptr_t fbf_buf_xp = base + offset; // register command in DMA chdev if( to_fbf ) dev_dma_remote_memcpy( fbf_buf_xp , mem_buf_xp , length ); else dev_dma_remote_memcpy( mem_buf_xp , fbf_buf_xp , length ); return 0; } // end dev_fbf_access() //////////////////////////////////////////// error_t dev_fbf_read( char * buffer, uint32_t length, uint32_t offset ) { #if DEBUG_DEV_FBF_RX uint32_t cycle = (uint32_t)hal_get_cycles(); if( DEBUG_DEV_FBF_RX < cycle ) printk("\n[DBG] %s : thread %x enter / process %x / vaddr %x / size %x\n", __FUNCTION__ , this, this->process->pid , buffer , buf_paddr ); #endif return dev_fbf_access( false , buffer , length , offset ); #if DEBUG_DEV_FBF_RX cycle = (uint32_t)hal_get_cycles(); if( DEBUG_DEV_FBF_RX < cycle ) printk("\n[DBG] %s : thread %x exit / process %x / vaddr %x / size %x\n", __FUNCTION__ , this, this->process->pid , buffer , buf_paddr ); #endif } //////////////////////////////////////////// error_t dev_fbf_write( char * buffer, uint32_t length, uint32_t offset ) { #if DEBUG_DEV_FBF_TX uint32_t cycle = (uint32_t)hal_get_cycles(); if( DEBUG_DEV_FBF_TX < cycle ) printk("\n[DBG] %s : thread %x enter / process %x / vaddr %x / size %x\n", __FUNCTION__ , this, this->process->pid , buffer , buf_paddr ); #endif return dev_fbf_access( true , buffer , length , offset ); #if DEBUG_DEV_FBF_RX cycle = (uint32_t)hal_get_cycles(); if( DEBUG_DEV_FBF_RX < cycle ) printk("\n[DBG] %s : thread %x exit / process %x / vaddr %x / size %x\n", __FUNCTION__ , this, this->process->pid , buffer , buf_paddr ); #endif }