| 1 | /* | 
|---|
| 2 |  * dev_fbf.c - FBF (Frame Buffer) generic device API implementation. | 
|---|
| 3 |  *  | 
|---|
| 4 |  * Author  Alain Greiner    (2016,2017,2018,2019) | 
|---|
| 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 <thread.h> | 
|---|
| 29 | #include <printk.h> | 
|---|
| 30 | #include <string.h> | 
|---|
| 31 | #include <chdev.h> | 
|---|
| 32 | #include <dev_fbf.h> | 
|---|
| 33 |  | 
|---|
| 34 | ///////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 35 | // Extern global variables | 
|---|
| 36 | ///////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 37 |  | 
|---|
| 38 | extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c | 
|---|
| 39 |  | 
|---|
| 40 | /////////////////////////////////////////// | 
|---|
| 41 | char * dev_fbf_cmd_str( uint32_t cmd_type ) | 
|---|
| 42 | { | 
|---|
| 43 |     if     ( cmd_type == FBF_READ       )  return "READ"; | 
|---|
| 44 |     else if( cmd_type == FBF_WRITE      )  return "WRITE"; | 
|---|
| 45 |     else if( cmd_type == FBF_GET_CONFIG )  return "GET_CONFIG"; | 
|---|
| 46 |     else                                   return "undefined"; | 
|---|
| 47 | } | 
|---|
| 48 |  | 
|---|
| 49 | //////////////////////////////////// | 
|---|
| 50 | void dev_fbf_init( chdev_t  * fbf ) | 
|---|
| 51 | { | 
|---|
| 52 |     // set chdev name | 
|---|
| 53 |     strcpy( fbf->name, "fbf" ); | 
|---|
| 54 |  | 
|---|
| 55 |     // call driver init function | 
|---|
| 56 |     hal_drivers_fbf_init( fbf ); | 
|---|
| 57 |  | 
|---|
| 58 | }  // end dev_fbf_init() | 
|---|
| 59 |  | 
|---|
| 60 | ////////////////////////////////////////// | 
|---|
| 61 | void dev_fbf_get_config( uint32_t * width, | 
|---|
| 62 |                          uint32_t * height, | 
|---|
| 63 |                          uint32_t * type ) | 
|---|
| 64 | { | 
|---|
| 65 |     // get extended pointer on FBF chdev descriptor | 
|---|
| 66 |     xptr_t  dev_xp = chdev_dir.fbf[0]; | 
|---|
| 67 |  | 
|---|
| 68 |     assert( (dev_xp != XPTR_NULL) , "undefined FBF chdev descriptor" ); | 
|---|
| 69 |  | 
|---|
| 70 |     // get FBF chdev cluster and local pointer | 
|---|
| 71 |     cxy_t     dev_cxy = GET_CXY( dev_xp ); | 
|---|
| 72 |     chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); | 
|---|
| 73 |  | 
|---|
| 74 |     // return values | 
|---|
| 75 |     *width  = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.width ) ); | 
|---|
| 76 |     *height = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.height ) ); | 
|---|
| 77 |     *type   = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->ext.fbf.subsampling ) ); | 
|---|
| 78 |  | 
|---|
| 79 | }  // end dev_fbf_get_config() | 
|---|
| 80 |  | 
|---|
| 81 | ///////////////////////////////////////////////////// | 
|---|
| 82 | error_t dev_fbf_move_data( uint32_t   cmd_type, | 
|---|
| 83 |                            void     * user_buffer, | 
|---|
| 84 |                            uint32_t   length, | 
|---|
| 85 |                            uint32_t   offset ) | 
|---|
| 86 | { | 
|---|
| 87 |     // get pointer on calling thread | 
|---|
| 88 |     thread_t * this = CURRENT_THREAD; | 
|---|
| 89 |  | 
|---|
| 90 | #if DEBUG_DEV_FBF | 
|---|
| 91 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
| 92 | if( DEBUG_DEV_FBF < cycle ) | 
|---|
| 93 | printk("\n[%s] thread[%x,%x] : %s / buffer %x / length %d / offset %x / cycle %d\n", | 
|---|
| 94 | __FUNCTION__ , this->process->pid, this->trdid,   | 
|---|
| 95 | dev_fbf_cmd_str(cmd_type), user_buffer, length, offset, cycle ); | 
|---|
| 96 | #endif | 
|---|
| 97 |  | 
|---|
| 98 |     // get pointers on FBF chdev | 
|---|
| 99 |     xptr_t      fbf_xp  = chdev_dir.fbf[0]; | 
|---|
| 100 |     cxy_t       fbf_cxy = GET_CXY( fbf_xp ); | 
|---|
| 101 |     chdev_t   * fbf_ptr = GET_PTR( fbf_xp ); | 
|---|
| 102 |  | 
|---|
| 103 | // check fbf_xp definition | 
|---|
| 104 | assert( (fbf_xp != XPTR_NULL) , "undefined FBF chdev descriptor" ); | 
|---|
| 105 |  | 
|---|
| 106 |     // get frame buffer width and height | 
|---|
| 107 |     uint32_t width  = hal_remote_l32 ( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.width ) ); | 
|---|
| 108 |     uint32_t height = hal_remote_l32 ( XPTR( fbf_cxy , &fbf_ptr->ext.fbf.height ) ); | 
|---|
| 109 |  | 
|---|
| 110 | // check offset and length versus FBF size | 
|---|
| 111 | assert( ((offset + length) <= (width * height)) , | 
|---|
| 112 | "offset %d / length %d / width %d / height %d\n", offset, length, width, height );  | 
|---|
| 113 |  | 
|---|
| 114 |     // register command in calling thread descriptor | 
|---|
| 115 |     this->fbf_cmd.dev_xp    = fbf_xp; | 
|---|
| 116 |     this->fbf_cmd.type      = cmd_type; | 
|---|
| 117 |     this->fbf_cmd.buffer    = user_buffer; | 
|---|
| 118 |     this->fbf_cmd.offset    = offset; | 
|---|
| 119 |     this->fbf_cmd.length    = length; | 
|---|
| 120 |  | 
|---|
| 121 |     // get driver command function | 
|---|
| 122 |     dev_cmd_t * cmd = (dev_cmd_t *)hal_remote_lpt( XPTR( fbf_cxy , &fbf_ptr->cmd ) ); | 
|---|
| 123 |  | 
|---|
| 124 |     // call driver  | 
|---|
| 125 |     cmd( XPTR( local_cxy , this ) ); | 
|---|
| 126 |  | 
|---|
| 127 |     error_t error = this->fbf_cmd.error; | 
|---|
| 128 |  | 
|---|
| 129 | #if DEBUG_DEV_FBF | 
|---|
| 130 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
| 131 | if( DEBUG_DEV_FBF < cycle ) | 
|---|
| 132 | printk("\n[%s] thread[%x,%x] completes %s / error = %d / cycle %d\n", | 
|---|
| 133 | __FUNCTION__ , this->process->pid, this->trdid,   | 
|---|
| 134 | dev_fbf_cmd_str(cmd_type), error , cycle ); | 
|---|
| 135 | #endif | 
|---|
| 136 |  | 
|---|
| 137 |     // return I/O operation status | 
|---|
| 138 |     return error; | 
|---|
| 139 |  | 
|---|
| 140 | }  // end dev_fbf_move_data() | 
|---|