| 1 | /* | 
|---|
| 2 |  * devfs.c - DEVFS File system API implementation. | 
|---|
| 3 |  * | 
|---|
| 4 |  * Author   Mohamed Lamine Karaoui (2014,2015) | 
|---|
| 5 |  *          Alain Greiner (2016,2017) | 
|---|
| 6 |  * | 
|---|
| 7 |  * Copyright (c) Sorbonne Universites | 
|---|
| 8 |  * | 
|---|
| 9 |  * This file is part of ALMOS-MKH. | 
|---|
| 10 |  * | 
|---|
| 11 |  * ALMOS-MKH is free software; you can redistribute it and/or modify it | 
|---|
| 12 |  * under the terms of the GNU General Public License as published by | 
|---|
| 13 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
| 14 |  * | 
|---|
| 15 |  * ALMOS-MKH is distributed in the hope that it will be useful, but | 
|---|
| 16 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 17 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 18 |  * General Public License for more details. | 
|---|
| 19 |  * | 
|---|
| 20 |  * You should have received a copy of the GNU General Public License | 
|---|
| 21 |  * along with ALMOS-MKH; if not, write to the Free Software Foundation, | 
|---|
| 22 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
| 23 |  */ | 
|---|
| 24 |  | 
|---|
| 25 | #include <hal_types.h> | 
|---|
| 26 | #include <hal_special.h> | 
|---|
| 27 | #include <printk.h> | 
|---|
| 28 | #include <kmem.h> | 
|---|
| 29 | #include <string.h> | 
|---|
| 30 | #include <chdev.h> | 
|---|
| 31 | #include <core.h> | 
|---|
| 32 | #include <thread.h> | 
|---|
| 33 | #include <vfs.h> | 
|---|
| 34 | #include <errno.h> | 
|---|
| 35 | #include <devfs.h> | 
|---|
| 36 | #include <rpc.h> | 
|---|
| 37 |  | 
|---|
| 38 |  | 
|---|
| 39 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 40 | //          Extern  variables          | 
|---|
| 41 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 42 |  | 
|---|
| 43 | extern vfs_ctx_t          fs_context[FS_TYPES_NR];   // allocated in vfs.c file | 
|---|
| 44 |  | 
|---|
| 45 | extern remote_barrier_t   global_barrier;            // allocated in kernel_init.c | 
|---|
| 46 |   | 
|---|
| 47 | extern chdev_directory_t  chdev_dir;                 // allocated in kernel_init.c | 
|---|
| 48 |  | 
|---|
| 49 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 50 | //                DEVFS private functions | 
|---|
| 51 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 52 |  | 
|---|
| 53 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 54 | // This function creates in the local cluster the dentry and the associated inode, | 
|---|
| 55 | // for a DEVFS directory (level 0 or level 1 in DEVFS tree). | 
|---|
| 56 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 57 | // @ name        : directory entry name. | 
|---|
| 58 | // @ parent_xp   : extended pointer on parent inode. | 
|---|
| 59 | // @ inode_xp    : [out] buffer for extended pointer on created inode. | 
|---|
| 60 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 61 | static void devfs_create_directory( char        * name, | 
|---|
| 62 |                                     xptr_t        parent_xp, | 
|---|
| 63 |                                     xptr_t      * inode_xp ) | 
|---|
| 64 | { | 
|---|
| 65 |     error_t       error; | 
|---|
| 66 |     xptr_t        new_dentry_xp;     // extended pointer on created dentry | 
|---|
| 67 |     xptr_t        new_inode_xp;      // extended pointer on created inode | 
|---|
| 68 |   | 
|---|
| 69 |     // get parent inode cluster and local pointer | 
|---|
| 70 |     cxy_t         parent_cxy = GET_CXY( parent_xp ); | 
|---|
| 71 |     vfs_inode_t * parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp ); | 
|---|
| 72 |  | 
|---|
| 73 |     // create vfs_dentry in cluster containing the parent inode | 
|---|
| 74 |     if( parent_cxy == local_cxy ) | 
|---|
| 75 |     { | 
|---|
| 76 |         error = vfs_dentry_create( FS_TYPE_DEVFS, | 
|---|
| 77 |                                    name, | 
|---|
| 78 |                                    parent_ptr, | 
|---|
| 79 |                                    &new_dentry_xp ); | 
|---|
| 80 |     } | 
|---|
| 81 |     else | 
|---|
| 82 |     { | 
|---|
| 83 |         rpc_vfs_dentry_create_client( parent_cxy, | 
|---|
| 84 |                                       FS_TYPE_DEVFS, | 
|---|
| 85 |                                       name, | 
|---|
| 86 |                                       parent_ptr, | 
|---|
| 87 |                                       &new_dentry_xp, | 
|---|
| 88 |                                       &error ); | 
|---|
| 89 |     } | 
|---|
| 90 |  | 
|---|
| 91 |     if ( error ) | 
|---|
| 92 |     { | 
|---|
| 93 |         printk("\n[PANIC] in %s : cannot create dentry for %s in cluster %x/n", | 
|---|
| 94 |                __FUNCTION__ , name , local_cxy ); | 
|---|
| 95 |         hal_core_sleep(); | 
|---|
| 96 |     } | 
|---|
| 97 |  | 
|---|
| 98 |     // create vfs_inode in local cluster TODO define the 4 arguments below [AG] | 
|---|
| 99 |     uint32_t  attr   = 0; | 
|---|
| 100 |     uint32_t  rights = 0; | 
|---|
| 101 |     uid_t     uid    = 0; | 
|---|
| 102 |     gid_t     gid    = 0; | 
|---|
| 103 |     error = vfs_inode_create( new_dentry_xp, | 
|---|
| 104 |                               FS_TYPE_DEVFS, | 
|---|
| 105 |                               INODE_TYPE_DIR, | 
|---|
| 106 |                               attr, | 
|---|
| 107 |                               rights, | 
|---|
| 108 |                               uid, | 
|---|
| 109 |                               gid, | 
|---|
| 110 |                               &new_inode_xp ); | 
|---|
| 111 |     if( error ) | 
|---|
| 112 |     { | 
|---|
| 113 |         printk("\n[PANIC] in %s : cannot create inode for %s in cluster %x/n", | 
|---|
| 114 |                __FUNCTION__ , name , local_cxy ); | 
|---|
| 115 |         hal_core_sleep(); | 
|---|
| 116 |     } | 
|---|
| 117 |  | 
|---|
| 118 |     // return extended pointer on directory inode | 
|---|
| 119 |     *inode_xp = new_inode_xp; | 
|---|
| 120 |  | 
|---|
| 121 | }  // end devfs_create_directory() | 
|---|
| 122 |                                      | 
|---|
| 123 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 124 | // This function creates in the local cluster the dentry and the associated inode, | 
|---|
| 125 | // for a chdev (level 2 in DEVFS tree). | 
|---|
| 126 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 127 | // @ chdev    : local pointer on local chdev. | 
|---|
| 128 | // @ name     : directory entry name. | 
|---|
| 129 | // @ parent   : local pointer on local parent inode. | 
|---|
| 130 | // @ inode_xp : [out] buffer for extended pointer on created inode. | 
|---|
| 131 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 132 | static void devfs_register_chdev( chdev_t     * chdev, | 
|---|
| 133 |                                   char        * name, | 
|---|
| 134 |                                   vfs_inode_t * parent, | 
|---|
| 135 |                                   xptr_t      * inode_xp ) | 
|---|
| 136 | { | 
|---|
| 137 |     error_t  error; | 
|---|
| 138 |     xptr_t   new_dentry_xp; | 
|---|
| 139 |     xptr_t   new_inode_xp; | 
|---|
| 140 |  | 
|---|
| 141 |     devfs_dmsg("\n[INFO] %s : create dentry for %s\n", __FUNCTION__ , name ); | 
|---|
| 142 |      | 
|---|
| 143 |     // create vfs_dentry in local cluster | 
|---|
| 144 |     error = vfs_dentry_create( FS_TYPE_DEVFS, | 
|---|
| 145 |                                name, | 
|---|
| 146 |                                parent, | 
|---|
| 147 |                                &new_dentry_xp ); | 
|---|
| 148 |     if ( error ) | 
|---|
| 149 |     { | 
|---|
| 150 |         printk("\n[PANIC] in %s : cannot create dentry for %s in cluster %x/n", | 
|---|
| 151 |                __FUNCTION__ , name , local_cxy ); | 
|---|
| 152 |         hal_core_sleep(); | 
|---|
| 153 |     } | 
|---|
| 154 |  | 
|---|
| 155 |     devfs_dmsg("\n[INFO] %s : create inode for %s\n", __FUNCTION__ , name ); | 
|---|
| 156 |      | 
|---|
| 157 |     // create vfs_inode in local cluster | 
|---|
| 158 |     uint32_t  attr   = 0; | 
|---|
| 159 |     uint32_t  rights = 0; | 
|---|
| 160 |     uid_t     uid    = 0; | 
|---|
| 161 |     gid_t     gid    = 0; | 
|---|
| 162 |     error = vfs_inode_create( new_dentry_xp, | 
|---|
| 163 |                               FS_TYPE_DEVFS, | 
|---|
| 164 |                               INODE_TYPE_DEV, | 
|---|
| 165 |                               attr, | 
|---|
| 166 |                               rights, | 
|---|
| 167 |                               uid, | 
|---|
| 168 |                               gid, | 
|---|
| 169 |                               &new_inode_xp ); | 
|---|
| 170 |     if( error ) | 
|---|
| 171 |     { | 
|---|
| 172 |         printk("\n[PANIC] in %s : cannot create inode for %s in cluster %x/n", | 
|---|
| 173 |                __FUNCTION__ , name , local_cxy ); | 
|---|
| 174 |         hal_core_sleep(); | 
|---|
| 175 |     } | 
|---|
| 176 |  | 
|---|
| 177 |     // return extended pointer on chdev inode | 
|---|
| 178 |     *inode_xp = new_inode_xp; | 
|---|
| 179 |      | 
|---|
| 180 | }  // end devfs_register_chdev() | 
|---|
| 181 |  | 
|---|
| 182 |  | 
|---|
| 183 |  | 
|---|
| 184 | /////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 185 | // Generic API : the following functions are called by the VFS,  | 
|---|
| 186 | //               and must be defined by all supported file systems. | 
|---|
| 187 | /////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 188 |  | 
|---|
| 189 | //////////////////////////////////////////// | 
|---|
| 190 |  | 
|---|
| 191 | //////////////////////////////////////////// | 
|---|
| 192 | error_t devfs_mount( xptr_t   parent_inode_xp, | 
|---|
| 193 |                      char   * devfs_root_name ) | 
|---|
| 194 | { | 
|---|
| 195 |     assert( (CURRENT_CORE->lid == 0) , __FUNCTION__ , "only CP0 should do it" ); | 
|---|
| 196 |  | 
|---|
| 197 |     vfs_inode_t * parent_inode_ptr; | 
|---|
| 198 |     cxy_t         parent_inode_cxy; | 
|---|
| 199 |     vfs_ctx_t   * vfs_ctx; | 
|---|
| 200 |  | 
|---|
| 201 |     char          node_name[16]; | 
|---|
| 202 |     uint32_t      channel; | 
|---|
| 203 |  | 
|---|
| 204 |     xptr_t        root_inode_xp; | 
|---|
| 205 |     xptr_t        external_inode_xp; | 
|---|
| 206 |     xptr_t        internal_inode_xp; | 
|---|
| 207 |     xptr_t        chdev_inode_xp; | 
|---|
| 208 |  | 
|---|
| 209 |     chdev_t     * chdev_ptr; | 
|---|
| 210 |  | 
|---|
| 211 |     // get number of kernel instances and extended pointer on global barrier  | 
|---|
| 212 |     cluster_t * cluster     = LOCAL_CLUSTER; | 
|---|
| 213 |     uint32_t    nb_clusters = cluster->x_size * cluster->y_size; | 
|---|
| 214 |     xptr_t      barrier_xp  = XPTR( cluster->io_cxy , &global_barrier ); | 
|---|
| 215 |  | 
|---|
| 216 |     // get VFS root inode cluster and local pointer | 
|---|
| 217 |     parent_inode_cxy = GET_CXY( parent_inode_xp ); | 
|---|
| 218 |     parent_inode_ptr = (vfs_inode_t *)GET_PTR( parent_inode_xp ); | 
|---|
| 219 |  | 
|---|
| 220 |     // get local pointer on VFS context for DEVFS | 
|---|
| 221 |     vfs_ctx = &fs_context[FS_TYPE_DEVFS]; | 
|---|
| 222 |  | 
|---|
| 223 |     ///// step 1 : all clusters initialize local DEVFS context  ///// | 
|---|
| 224 |  | 
|---|
| 225 |     devfs_ctx_init( vfs_ctx , parent_inode_xp ); | 
|---|
| 226 |  | 
|---|
| 227 |     ///// step 2 : cluster_0 creates DEVFS root    ///// | 
|---|
| 228 |  | 
|---|
| 229 |     if( local_cxy == 0 ) | 
|---|
| 230 |     { | 
|---|
| 231 |         devfs_create_directory( devfs_root_name, | 
|---|
| 232 |                                 parent_inode_xp, | 
|---|
| 233 |                                 &root_inode_xp ); | 
|---|
| 234 |     } | 
|---|
| 235 |  | 
|---|
| 236 |     // synchronize all clusters | 
|---|
| 237 |     remote_barrier( barrier_xp , nb_clusters ); | 
|---|
| 238 |  | 
|---|
| 239 |     ///// step 3 : all clusters create "internal" directory and chdevs  ///// | 
|---|
| 240 |  | 
|---|
| 241 |     // TODO check device existence : (chdev_xp != XPTR_NULL) in chdev_dir | 
|---|
| 242 |  | 
|---|
| 243 |     snprintf( node_name , 16 , "internal_%x" , local_cxy ); | 
|---|
| 244 |  | 
|---|
| 245 |     devfs_create_directory( node_name, | 
|---|
| 246 |                             root_inode_xp, | 
|---|
| 247 |                             &internal_inode_xp ); | 
|---|
| 248 |  | 
|---|
| 249 |     // create ICU chdev inode | 
|---|
| 250 |     chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.icu[local_cxy] ); | 
|---|
| 251 |     devfs_register_chdev( chdev_ptr, | 
|---|
| 252 |                           "icu", | 
|---|
| 253 |                           (vfs_inode_t *)GET_PTR( internal_inode_xp ), | 
|---|
| 254 |                           &chdev_inode_xp ); | 
|---|
| 255 |  | 
|---|
| 256 |     // create MMC chdev inode | 
|---|
| 257 |     chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.mmc[local_cxy] ); | 
|---|
| 258 |     devfs_register_chdev( chdev_ptr, | 
|---|
| 259 |                           "mmc",  | 
|---|
| 260 |                           (vfs_inode_t *)GET_PTR( internal_inode_xp ), | 
|---|
| 261 |                           &chdev_inode_xp ); | 
|---|
| 262 |  | 
|---|
| 263 |     // create DMA chdev inodes (one DMA channel per core) | 
|---|
| 264 |     for( channel = 0 ; channel < cluster->cores_nr ; channel++ ) | 
|---|
| 265 |     { | 
|---|
| 266 |         chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.dma[channel] ); | 
|---|
| 267 |         snprintf( node_name , 16 , "dma_%d" , channel ); | 
|---|
| 268 |         devfs_register_chdev( chdev_ptr, | 
|---|
| 269 |                               node_name, | 
|---|
| 270 |                               (vfs_inode_t *)GET_PTR( internal_inode_xp ), | 
|---|
| 271 |                               &chdev_inode_xp ); | 
|---|
| 272 |     } | 
|---|
| 273 |  | 
|---|
| 274 |     ///// step 4 : cluster_io creates "external" directory and chdevs ///// | 
|---|
| 275 |  | 
|---|
| 276 |     // TODO check device existence : (chdev_xp != XPTR_NULL) in chdev_dir | 
|---|
| 277 |  | 
|---|
| 278 |     if( local_cxy == cluster->io_cxy ) | 
|---|
| 279 |     { | 
|---|
| 280 |         devfs_create_directory( "external", | 
|---|
| 281 |                                 root_inode_xp, | 
|---|
| 282 |                                 &external_inode_xp ); | 
|---|
| 283 |  | 
|---|
| 284 |         // create IOB chdev inode | 
|---|
| 285 |         chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.iob ); | 
|---|
| 286 |         devfs_register_chdev( chdev_ptr, | 
|---|
| 287 |                               "iob", | 
|---|
| 288 |                               (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
| 289 |                               &chdev_inode_xp ); | 
|---|
| 290 |          | 
|---|
| 291 |         // create PIC chdev inode | 
|---|
| 292 |         chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.pic ); | 
|---|
| 293 |         devfs_register_chdev( chdev_ptr, | 
|---|
| 294 |                               "pic", | 
|---|
| 295 |                               (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
| 296 |                               &chdev_inode_xp ); | 
|---|
| 297 |  | 
|---|
| 298 |         // create TXT chdev inodes | 
|---|
| 299 |         for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ ) | 
|---|
| 300 |         { | 
|---|
| 301 |             chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.txt[channel] ); | 
|---|
| 302 |             snprintf( node_name , 16 , "txt_%d" , channel ); | 
|---|
| 303 |             devfs_register_chdev( chdev_ptr, | 
|---|
| 304 |                                   node_name, | 
|---|
| 305 |                                   (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
| 306 |                                   &chdev_inode_xp ); | 
|---|
| 307 |         } | 
|---|
| 308 |  | 
|---|
| 309 |         // create IOC chdev inodes | 
|---|
| 310 |         for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ ) | 
|---|
| 311 |         { | 
|---|
| 312 |             chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.ioc[channel] ); | 
|---|
| 313 |             snprintf( node_name , 16 , "ioc_%d" , channel ); | 
|---|
| 314 |             devfs_register_chdev( chdev_ptr, | 
|---|
| 315 |                                   node_name, | 
|---|
| 316 |                                   (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
| 317 |                                   &chdev_inode_xp ); | 
|---|
| 318 |         } | 
|---|
| 319 |  | 
|---|
| 320 |         // create FBF chdev inodes | 
|---|
| 321 |         for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ ) | 
|---|
| 322 |         { | 
|---|
| 323 |             chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.ioc[channel] ); | 
|---|
| 324 |             snprintf( node_name , 16 , "fbf_%d" , channel ); | 
|---|
| 325 |             devfs_register_chdev( chdev_ptr, | 
|---|
| 326 |                                   node_name, | 
|---|
| 327 |                                   (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
| 328 |                                   &chdev_inode_xp ); | 
|---|
| 329 |         } | 
|---|
| 330 |  | 
|---|
| 331 |         // create NIC_RX chdevs | 
|---|
| 332 |         for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) | 
|---|
| 333 |         { | 
|---|
| 334 |             chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.nic_rx[channel] ); | 
|---|
| 335 |             snprintf( node_name , 16 , "nic_rx_%d" , channel ); | 
|---|
| 336 |             devfs_register_chdev( chdev_ptr, | 
|---|
| 337 |                                   node_name, | 
|---|
| 338 |                                   (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
| 339 |                                   &chdev_inode_xp ); | 
|---|
| 340 |         } | 
|---|
| 341 |  | 
|---|
| 342 |         // create NIC_TX chdev inodes | 
|---|
| 343 |         for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) | 
|---|
| 344 |         { | 
|---|
| 345 |             chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.nic_tx[channel] ); | 
|---|
| 346 |             snprintf( node_name , 16 , "nic_tx_%d" , channel ); | 
|---|
| 347 |             devfs_register_chdev( chdev_ptr, | 
|---|
| 348 |                                   node_name, | 
|---|
| 349 |                                   (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
| 350 |                                   &chdev_inode_xp ); | 
|---|
| 351 |         } | 
|---|
| 352 |     } | 
|---|
| 353 |  | 
|---|
| 354 |     // synchronize all clusters | 
|---|
| 355 |     remote_barrier( barrier_xp , nb_clusters ); | 
|---|
| 356 |  | 
|---|
| 357 |     return 0; | 
|---|
| 358 |  | 
|---|
| 359 | }  // end devfs_init() | 
|---|
| 360 |  | 
|---|
| 361 |  | 
|---|
| 362 | //////////////////////////////////////////// | 
|---|
| 363 | error_t devfs_ctx_init( vfs_ctx_t * vfs_ctx, | 
|---|
| 364 |                         xptr_t      root_inode_xp ) | 
|---|
| 365 | { | 
|---|
| 366 |     vfs_ctx->type    = FS_TYPE_DEVFS; | 
|---|
| 367 |     vfs_ctx->attr    = 0;                // not READ_ONLY / not SYNC | 
|---|
| 368 |     vfs_ctx->count   = 0;                // unused for DEVFS | 
|---|
| 369 |     vfs_ctx->blksize = 0;                // unused for DEVFS | 
|---|
| 370 |     vfs_ctx->root_xp = root_inode_xp; | 
|---|
| 371 |     vfs_ctx->extend  = NULL;             // unused for DEVFS | 
|---|
| 372 |  | 
|---|
| 373 |     spinlock_init( &vfs_ctx->lock ); | 
|---|
| 374 |  | 
|---|
| 375 |     bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES ); | 
|---|
| 376 |  | 
|---|
| 377 |     return 0; | 
|---|
| 378 | } | 
|---|
| 379 |  | 
|---|
| 380 |  | 
|---|
| 381 | //////////////////////////////////////////////////// | 
|---|
| 382 | error_t devfs_inode_create( vfs_inode_t * vfs_inode, | 
|---|
| 383 |                             chdev_t     * chdev ) | 
|---|
| 384 | { | 
|---|
| 385 |     kmem_req_t      req; | 
|---|
| 386 |     devfs_inode_t * devfs_inode; | 
|---|
| 387 |  | 
|---|
| 388 |     // allocate memory for FATFS inode extension | 
|---|
| 389 |         req.type    = KMEM_DEVFS_INODE; | 
|---|
| 390 |         req.size    = sizeof(devfs_inode_t); | 
|---|
| 391 |     req.flags   = AF_KERNEL | AF_ZERO; | 
|---|
| 392 |         devfs_inode = (devfs_inode_t *)kmem_alloc( &req ); | 
|---|
| 393 |  | 
|---|
| 394 |     if( devfs_inode == NULL ) return ENOMEM; | 
|---|
| 395 |  | 
|---|
| 396 |     // link DEVFS inode to VFS inode | 
|---|
| 397 |     vfs_inode->extend = devfs_inode; | 
|---|
| 398 |  | 
|---|
| 399 |     // initialise DEVFS inode   | 
|---|
| 400 |     devfs_inode->chdev = chdev; | 
|---|
| 401 |   | 
|---|
| 402 |     return 0; | 
|---|
| 403 | } | 
|---|
| 404 |  | 
|---|
| 405 | /////////////////////////////////////////////////// | 
|---|
| 406 | void devfs_inode_destroy( vfs_inode_t * vfs_inode ) | 
|---|
| 407 | { | 
|---|
| 408 |     kmem_req_t      req; | 
|---|
| 409 |     devfs_inode_t * devfs_inode; | 
|---|
| 410 |  | 
|---|
| 411 |     // get pointer on DEVFS inode  | 
|---|
| 412 |     devfs_inode = (devfs_inode_t *)vfs_inode->extend; | 
|---|
| 413 |  | 
|---|
| 414 |     req.type = KMEM_DEVFS_INODE; | 
|---|
| 415 |     req.ptr  = devfs_inode; | 
|---|
| 416 |     kmem_free( &req ); | 
|---|
| 417 |  | 
|---|
| 418 |         vfs_inode->extend = NULL; | 
|---|
| 419 | } | 
|---|
| 420 |  | 
|---|
| 421 |  | 
|---|
| 422 | /* deprecated [AG] | 
|---|
| 423 |  | 
|---|
| 424 | error_t devfs_open_file( vfs_file_t * file, | 
|---|
| 425 |                          void       * extend ); | 
|---|
| 426 | { | 
|---|
| 427 |         error_t err; | 
|---|
| 428 |         register struct devfs_context_s *ctx; | 
|---|
| 429 |         register struct devfs_file_s *info; | 
|---|
| 430 |         chdev_t       * chdev; | 
|---|
| 431 |         vfs_inode_t   * inode; | 
|---|
| 432 |         dev_request_t   rq; | 
|---|
| 433 |         kmem_req_t      req; | 
|---|
| 434 |  | 
|---|
| 435 |         inode = file->inode; | 
|---|
| 436 |  | 
|---|
| 437 |         info = file->fr_pv; | 
|---|
| 438 |         ctx  = (struct devfs_context_s *)&inode->i_ctx->ctx_devfs; | 
|---|
| 439 |  | 
|---|
| 440 |         if(!(inode->i_attr & VFS_DIR)) | 
|---|
| 441 |         { | 
|---|
| 442 |                 dev = (struct device_s*)inode->i_pv; | 
|---|
| 443 |      | 
|---|
| 444 |                 if(dev->type == DEV_INTERNAL) | 
|---|
| 445 |                         return EPERM; | 
|---|
| 446 |  | 
|---|
| 447 |                 if(dev->type == DEV_BLK) | 
|---|
| 448 |                         VFS_SET(inode->i_attr,VFS_DEV_BLK); | 
|---|
| 449 |                 else | 
|---|
| 450 |                         VFS_SET(inode->i_attr,VFS_DEV_CHR); | 
|---|
| 451 |   | 
|---|
| 452 |                 if(dev->op.dev.open != NULL) | 
|---|
| 453 |                 { | 
|---|
| 454 |                         rq.fremote = file; | 
|---|
| 455 |                         if((err=dev->op.dev.open(dev, &rq))) | 
|---|
| 456 |                                 return err; | 
|---|
| 457 |                 } | 
|---|
| 458 |  | 
|---|
| 459 |                 priv->dev = (void*)dev; | 
|---|
| 460 |  | 
|---|
| 461 |                 return 0; | 
|---|
| 462 |         } | 
|---|
| 463 |  | 
|---|
| 464 |         if(info == NULL) | 
|---|
| 465 |         { | 
|---|
| 466 |                 req.type  = KMEM_DEVFS_FILE; | 
|---|
| 467 |                 req.size  = sizeof(*info); | 
|---|
| 468 |                 req.flags = AF_KERNEL; | 
|---|
| 469 |                 info      = kmem_alloc(&req); | 
|---|
| 470 |         } | 
|---|
| 471 |  | 
|---|
| 472 |         if(info == NULL) return ENOMEM; | 
|---|
| 473 |  | 
|---|
| 474 |         metafs_iter_init(&devfs_db.root, &info->iter); | 
|---|
| 475 |         info->ctx  = ctx; | 
|---|
| 476 |         file->fr_pv = info; | 
|---|
| 477 |    | 
|---|
| 478 |         metafs_print(&devfs_db.root); | 
|---|
| 479 |         return 0; | 
|---|
| 480 | } | 
|---|
| 481 |  | 
|---|
| 482 | #define TMP_BUFF_SZ 512 | 
|---|
| 483 |  | 
|---|
| 484 | //FIXME: | 
|---|
| 485 | //add a "while" loop for the case where the | 
|---|
| 486 | //buffer TMP_BUFF_SZ is smaller than | 
|---|
| 487 | //buffer->size | 
|---|
| 488 | ////////////////////////////// | 
|---|
| 489 | devfs_read( vfs_file_t * file, | 
|---|
| 490 |             char       * buffer ) | 
|---|
| 491 | { | 
|---|
| 492 |         chdev_t       * chdev; | 
|---|
| 493 |         dev_request_t   rq; | 
|---|
| 494 |         uint32_t        count; | 
|---|
| 495 |     uint8_t         buff[TMP_BUFF_SZ]; | 
|---|
| 496 |  | 
|---|
| 497 |     // get pointer on chdev | 
|---|
| 498 |         chdev = (chdev_t *)file->extend; | 
|---|
| 499 |  | 
|---|
| 500 |     if( chdev->func == DEV_FUNC_TXT ) | 
|---|
| 501 |     { | 
|---|
| 502 |     } | 
|---|
| 503 |     if( chdev->func == DEV_FUNC_IOC ) | 
|---|
| 504 |     { | 
|---|
| 505 |     } | 
|---|
| 506 |     else | 
|---|
| 507 |     { | 
|---|
| 508 |         printk("\n[PANIC] in %s : illegal device functionnal type | 
|---|
| 509 |  | 
|---|
| 510 |         rq.dst   = &buff[0]; | 
|---|
| 511 |         rq.count = TMP_BUFF_SZ; | 
|---|
| 512 |         rq.flags = 0; | 
|---|
| 513 |         rq.file  = file; | 
|---|
| 514 |  | 
|---|
| 515 |         if((count = dev->op.dev.read(dev, &rq)) < 0) | 
|---|
| 516 |                 return count; | 
|---|
| 517 |  | 
|---|
| 518 |         buffer->scpy_to_buff(buffer, &buff[0], count); | 
|---|
| 519 |         return count; | 
|---|
| 520 | } | 
|---|
| 521 |  | 
|---|
| 522 | //FIXME: To improve this an avoid the extra copy, | 
|---|
| 523 | //we could set along with the buffer(src and dest)  | 
|---|
| 524 | //the functions to manipulate them, such as in  | 
|---|
| 525 | //do_exec.c | 
|---|
| 526 | /////////////////////////////// | 
|---|
| 527 | devfs_write( vfs_file_t * file, | 
|---|
| 528 |              char       * buffer ) | 
|---|
| 529 | { | 
|---|
| 530 |         register struct device_s *dev; | 
|---|
| 531 |         uint8_t buff[TMP_BUFF_SZ]; | 
|---|
| 532 |         dev_request_t rq; | 
|---|
| 533 |          | 
|---|
| 534 |         dev = (struct device_s*)file->f_private.dev; | 
|---|
| 535 |          | 
|---|
| 536 |         //FIXME avoid the extra copy ? | 
|---|
| 537 |         buffer->scpy_from_buff(buffer, (void*)&buff[0], TMP_BUFF_SZ); | 
|---|
| 538 |         rq.src   = (void*)&buff[0]; | 
|---|
| 539 |         rq.count = buffer->size; | 
|---|
| 540 |         rq.flags = 0; | 
|---|
| 541 |         rq.file  = file; | 
|---|
| 542 |    | 
|---|
| 543 |         return dev->op.dev.write(dev, &rq); | 
|---|
| 544 | } | 
|---|
| 545 |  | 
|---|
| 546 | VFS_LSEEK_FILE(devfs_lseek) | 
|---|
| 547 | { | 
|---|
| 548 |         register struct device_s *dev; | 
|---|
| 549 |         dev_request_t rq; | 
|---|
| 550 |  | 
|---|
| 551 |         dev = (struct device_s*)file->fr_inode->i_pv; | 
|---|
| 552 |  | 
|---|
| 553 |         if(dev->op.dev.lseek == NULL) | 
|---|
| 554 |                 return VFS_ENOTUSED; | 
|---|
| 555 |    | 
|---|
| 556 |         rq.fremote = file; | 
|---|
| 557 |         return dev->op.dev.lseek(dev, &rq); | 
|---|
| 558 | } | 
|---|
| 559 |  | 
|---|
| 560 | VFS_CLOSE_FILE(devfs_close) | 
|---|
| 561 | { | 
|---|
| 562 |         register struct device_s *dev; | 
|---|
| 563 |         dev_request_t rq; | 
|---|
| 564 |  | 
|---|
| 565 |         if(file->fr_inode->i_attr & VFS_DIR) | 
|---|
| 566 |                 return 0; | 
|---|
| 567 |  | 
|---|
| 568 |         dev = (struct device_s*)file->fr_inode->i_pv; | 
|---|
| 569 |  | 
|---|
| 570 |         if(dev->op.dev.close == NULL) | 
|---|
| 571 |                 return 0; | 
|---|
| 572 |    | 
|---|
| 573 |         rq.fremote = file; | 
|---|
| 574 |         return dev->op.dev.close(dev, &rq); | 
|---|
| 575 | } | 
|---|
| 576 |  | 
|---|
| 577 | VFS_RELEASE_FILE(devfs_release) | 
|---|
| 578 | {   | 
|---|
| 579 |         kmem_req_t req; | 
|---|
| 580 |  | 
|---|
| 581 |         if(file->fr_pv == NULL)  | 
|---|
| 582 |                 return 0; | 
|---|
| 583 |    | 
|---|
| 584 |         req.type = KMEM_DEVFS_FILE; | 
|---|
| 585 |         req.ptr  = file->fr_pv; | 
|---|
| 586 |         kmem_free(&req); | 
|---|
| 587 |  | 
|---|
| 588 |         file->fr_pv = NULL; | 
|---|
| 589 |         return 0; | 
|---|
| 590 | } | 
|---|
| 591 |  | 
|---|
| 592 | VFS_READ_DIR(devfs_readdir) | 
|---|
| 593 | { | 
|---|
| 594 |         register struct devfs_file_s *info; | 
|---|
| 595 |         register struct metafs_s *current; | 
|---|
| 596 |         register struct device_s *current_dev; | 
|---|
| 597 |    | 
|---|
| 598 |         info = file->fr_pv; | 
|---|
| 599 |    | 
|---|
| 600 |         if(file->fr_pv == NULL) | 
|---|
| 601 |                 return ENOTDIR; | 
|---|
| 602 |  | 
|---|
| 603 |         if((current = metafs_lookup_next(&devfs_db.root, &info->iter)) == NULL) | 
|---|
| 604 |                 return EEODIR; | 
|---|
| 605 |  | 
|---|
| 606 |         current_dev    = metafs_container(current, struct device_s, node); | 
|---|
| 607 |         dirent->u_attr = (current_dev->type == DEV_BLK) ? VFS_DEV_BLK : VFS_DEV_CHR; | 
|---|
| 608 |  | 
|---|
| 609 |         strcpy((char*)dirent->u_name, metafs_get_name(current)); | 
|---|
| 610 |  | 
|---|
| 611 |         dirent->u_ino = (uint_t) current_dev->base_paddr; | 
|---|
| 612 |  | 
|---|
| 613 |         return 0; | 
|---|
| 614 | } | 
|---|
| 615 |  | 
|---|
| 616 | VFS_MMAP_FILE(devfs_mmap) | 
|---|
| 617 | { | 
|---|
| 618 |         register struct device_s *dev; | 
|---|
| 619 |         dev_request_t rq; | 
|---|
| 620 |    | 
|---|
| 621 |         dev = (struct device_s*)file->f_private.dev; | 
|---|
| 622 |  | 
|---|
| 623 |         if(dev->op.dev.mmap == NULL) | 
|---|
| 624 |                 return ENODEV; | 
|---|
| 625 |  | 
|---|
| 626 |         rq.flags  = 0; | 
|---|
| 627 |         rq.file   = file; | 
|---|
| 628 |         rq.region = region; | 
|---|
| 629 |  | 
|---|
| 630 |         return dev->op.dev.mmap(dev, &rq); | 
|---|
| 631 | } | 
|---|
| 632 |  | 
|---|
| 633 | VFS_MMAP_FILE(devfs_munmap) | 
|---|
| 634 | { | 
|---|
| 635 |         register struct device_s *dev; | 
|---|
| 636 |         dev_request_t rq; | 
|---|
| 637 |  | 
|---|
| 638 |         dev = (struct device_s*)file->f_private.dev; | 
|---|
| 639 |  | 
|---|
| 640 |         if(dev->op.dev.munmap == NULL) | 
|---|
| 641 |                 return ENODEV; | 
|---|
| 642 |  | 
|---|
| 643 |         rq.flags  = 0; | 
|---|
| 644 |         rq.file   = file; | 
|---|
| 645 |         rq.region = region; | 
|---|
| 646 |  | 
|---|
| 647 |         return dev->op.dev.munmap(dev, &rq); | 
|---|
| 648 | } | 
|---|
| 649 |  | 
|---|
| 650 |  | 
|---|
| 651 | */ | 
|---|
| 652 |  | 
|---|
| 653 |  | 
|---|