| [23] | 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 | printk("\n        @@@ devfs_chdev : 0 / name = %s\n", 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 |  | 
|---|
|  | 149 | printk("\n        @@@ devfs_chdev : 1 / name = %s\n", name ); | 
|---|
|  | 150 |  | 
|---|
|  | 151 | if ( error ) | 
|---|
|  | 152 | { | 
|---|
|  | 153 | printk("\n[PANIC] in %s : cannot create dentry for %s in cluster %x/n", | 
|---|
|  | 154 | __FUNCTION__ , name , local_cxy ); | 
|---|
|  | 155 | hal_core_sleep(); | 
|---|
|  | 156 | } | 
|---|
|  | 157 |  | 
|---|
|  | 158 | printk("\n        @@@ devfs_chdev : 2 / name = %s\n", name ); | 
|---|
|  | 159 |  | 
|---|
|  | 160 | // create vfs_inode in local cluster | 
|---|
|  | 161 | uint32_t  attr   = 0; | 
|---|
|  | 162 | uint32_t  rights = 0; | 
|---|
|  | 163 | uid_t     uid    = 0; | 
|---|
|  | 164 | gid_t     gid    = 0; | 
|---|
|  | 165 | error = vfs_inode_create( new_dentry_xp, | 
|---|
|  | 166 | FS_TYPE_DEVFS, | 
|---|
|  | 167 | INODE_TYPE_DEV, | 
|---|
|  | 168 | attr, | 
|---|
|  | 169 | rights, | 
|---|
|  | 170 | uid, | 
|---|
|  | 171 | gid, | 
|---|
|  | 172 | &new_inode_xp ); | 
|---|
|  | 173 |  | 
|---|
|  | 174 | printk("\n        @@@ devfs_chdev : 3 / name = %s\n", name ); | 
|---|
|  | 175 |  | 
|---|
|  | 176 | if( error ) | 
|---|
|  | 177 | { | 
|---|
|  | 178 | printk("\n[PANIC] in %s : cannot create inode for %s in cluster %x/n", | 
|---|
|  | 179 | __FUNCTION__ , name , local_cxy ); | 
|---|
|  | 180 | hal_core_sleep(); | 
|---|
|  | 181 | } | 
|---|
|  | 182 |  | 
|---|
|  | 183 | // return extended pointer on chdev inode | 
|---|
|  | 184 | *inode_xp = new_inode_xp; | 
|---|
|  | 185 |  | 
|---|
|  | 186 | }  // end devfs_register_chdev() | 
|---|
|  | 187 |  | 
|---|
|  | 188 |  | 
|---|
|  | 189 |  | 
|---|
|  | 190 | /////////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 191 | // Generic API : the following functions are called by the VFS, | 
|---|
|  | 192 | //               and must be defined by all supported file systems. | 
|---|
|  | 193 | /////////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 194 |  | 
|---|
|  | 195 | //////////////////////////////////////////// | 
|---|
|  | 196 |  | 
|---|
|  | 197 | //////////////////////////////////////////// | 
|---|
|  | 198 | error_t devfs_mount( xptr_t   parent_inode_xp, | 
|---|
|  | 199 | char   * devfs_root_name ) | 
|---|
|  | 200 | { | 
|---|
|  | 201 | assert( (CURRENT_CORE->lid == 0) , __FUNCTION__ , "only CP0 should do it" ); | 
|---|
|  | 202 |  | 
|---|
|  | 203 | vfs_inode_t * parent_inode_ptr; | 
|---|
|  | 204 | cxy_t         parent_inode_cxy; | 
|---|
|  | 205 | vfs_ctx_t   * vfs_ctx; | 
|---|
|  | 206 |  | 
|---|
|  | 207 | char          node_name[16]; | 
|---|
|  | 208 | uint32_t      channel; | 
|---|
|  | 209 |  | 
|---|
|  | 210 | xptr_t        root_inode_xp; | 
|---|
|  | 211 | xptr_t        external_inode_xp; | 
|---|
|  | 212 | xptr_t        internal_inode_xp; | 
|---|
|  | 213 | xptr_t        chdev_inode_xp; | 
|---|
|  | 214 |  | 
|---|
|  | 215 | chdev_t     * chdev_ptr; | 
|---|
|  | 216 |  | 
|---|
|  | 217 | // get number of kernel instances and extended pointer on global barrier | 
|---|
|  | 218 | cluster_t * cluster     = LOCAL_CLUSTER; | 
|---|
|  | 219 | uint32_t    nb_clusters = cluster->x_size * cluster->y_size; | 
|---|
|  | 220 | xptr_t      barrier_xp  = XPTR( cluster->io_cxy , &global_barrier ); | 
|---|
|  | 221 |  | 
|---|
|  | 222 | // get VFS root inode cluster and local pointer | 
|---|
|  | 223 | parent_inode_cxy = GET_CXY( parent_inode_xp ); | 
|---|
|  | 224 | parent_inode_ptr = (vfs_inode_t *)GET_PTR( parent_inode_xp ); | 
|---|
|  | 225 |  | 
|---|
|  | 226 | // get local pointer on VFS context for DEVFS | 
|---|
|  | 227 | vfs_ctx = &fs_context[FS_TYPE_DEVFS]; | 
|---|
|  | 228 |  | 
|---|
|  | 229 | ///// step 1 : all clusters initialize local DEVFS context  ///// | 
|---|
|  | 230 |  | 
|---|
|  | 231 | printk("\n    @@@ devfs_mount : 0 / name = %s\n", devfs_root_name ); | 
|---|
|  | 232 |  | 
|---|
|  | 233 | devfs_ctx_init( vfs_ctx , parent_inode_xp ); | 
|---|
|  | 234 |  | 
|---|
|  | 235 | ///// step 2 : cluster_0 creates DEVFS root    ///// | 
|---|
|  | 236 |  | 
|---|
|  | 237 | printk("\n    @@@ devfs_mount : 1 / name = %s\n", devfs_root_name ); | 
|---|
|  | 238 |  | 
|---|
|  | 239 | if( local_cxy == 0 ) | 
|---|
|  | 240 | { | 
|---|
|  | 241 | devfs_create_directory( devfs_root_name, | 
|---|
|  | 242 | parent_inode_xp, | 
|---|
|  | 243 | &root_inode_xp ); | 
|---|
|  | 244 | printk("\n    @@@ devfs_mount : 2\n"); | 
|---|
|  | 245 |  | 
|---|
|  | 246 | } | 
|---|
|  | 247 |  | 
|---|
|  | 248 | // synchronize all clusters | 
|---|
|  | 249 | remote_barrier( barrier_xp , nb_clusters ); | 
|---|
|  | 250 |  | 
|---|
|  | 251 | ///// step 3 : all clusters create "internal" directory and chdevs  ///// | 
|---|
|  | 252 |  | 
|---|
|  | 253 | printk("\n    @@@ devfs_mount : 3 / name = %s\n", devfs_root_name ); | 
|---|
|  | 254 |  | 
|---|
|  | 255 | snprintf( node_name , 16 , "internal_%x" , local_cxy ); | 
|---|
|  | 256 |  | 
|---|
|  | 257 | printk("\n    @@@ devfs_mount : 4 / name = %s\n", devfs_root_name ); | 
|---|
|  | 258 |  | 
|---|
|  | 259 | devfs_create_directory( node_name, | 
|---|
|  | 260 | root_inode_xp, | 
|---|
|  | 261 | &internal_inode_xp ); | 
|---|
|  | 262 |  | 
|---|
|  | 263 | printk("\n    @@@ devfs_mount : 5 / name = %s\n", devfs_root_name ); | 
|---|
|  | 264 |  | 
|---|
|  | 265 | // create ICU chdev inode | 
|---|
|  | 266 | chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.icu[local_cxy] ); | 
|---|
|  | 267 | devfs_register_chdev( chdev_ptr, | 
|---|
|  | 268 | "icu", | 
|---|
|  | 269 | (vfs_inode_t *)GET_PTR( internal_inode_xp ), | 
|---|
|  | 270 | &chdev_inode_xp ); | 
|---|
|  | 271 |  | 
|---|
|  | 272 | printk("\n    @@@ devfs_mount : 6 / name = %s\n", devfs_root_name ); | 
|---|
|  | 273 |  | 
|---|
|  | 274 | // create MMC chdev inode | 
|---|
|  | 275 | chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.mmc[local_cxy] ); | 
|---|
|  | 276 | devfs_register_chdev( chdev_ptr, | 
|---|
|  | 277 | "mmc", | 
|---|
|  | 278 | (vfs_inode_t *)GET_PTR( internal_inode_xp ), | 
|---|
|  | 279 | &chdev_inode_xp ); | 
|---|
|  | 280 |  | 
|---|
|  | 281 | printk("\n    @@@ devfs_mount : 7 / name = %s\n", devfs_root_name ); | 
|---|
|  | 282 |  | 
|---|
|  | 283 | // create DMA chdev inodes (one DMA channel per core) | 
|---|
|  | 284 | for( channel = 0 ; channel < cluster->cores_nr ; channel++ ) | 
|---|
|  | 285 | { | 
|---|
|  | 286 | chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.dma[channel] ); | 
|---|
|  | 287 | snprintf( node_name , 16 , "dma_%d" , channel ); | 
|---|
|  | 288 | devfs_register_chdev( chdev_ptr, | 
|---|
|  | 289 | node_name, | 
|---|
|  | 290 | (vfs_inode_t *)GET_PTR( internal_inode_xp ), | 
|---|
|  | 291 | &chdev_inode_xp ); | 
|---|
|  | 292 |  | 
|---|
|  | 293 | printk("\n    @@@ devfs_mount : 8 / name = %s\n", devfs_root_name ); | 
|---|
|  | 294 |  | 
|---|
|  | 295 | } | 
|---|
|  | 296 |  | 
|---|
|  | 297 | ///// step 4 : cluster_io creates "external" directory and chdevs ///// | 
|---|
|  | 298 |  | 
|---|
|  | 299 | if( local_cxy == cluster->io_cxy ) | 
|---|
|  | 300 | { | 
|---|
|  | 301 | devfs_create_directory( "external", | 
|---|
|  | 302 | root_inode_xp, | 
|---|
|  | 303 | &external_inode_xp ); | 
|---|
|  | 304 |  | 
|---|
|  | 305 | printk("\n    @@@ devfs_mount : 9 / name = %s\n", devfs_root_name ); | 
|---|
|  | 306 |  | 
|---|
|  | 307 | // create IOB chdev inode | 
|---|
|  | 308 | chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.iob ); | 
|---|
|  | 309 | devfs_register_chdev( chdev_ptr, | 
|---|
|  | 310 | "iob", | 
|---|
|  | 311 | (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
|  | 312 | &chdev_inode_xp ); | 
|---|
|  | 313 |  | 
|---|
|  | 314 | printk("\n    @@@ devfs_mount : 10 / name = %s\n", devfs_root_name ); | 
|---|
|  | 315 |  | 
|---|
|  | 316 | // create PIC chdev inode | 
|---|
|  | 317 | chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.pic ); | 
|---|
|  | 318 | devfs_register_chdev( chdev_ptr, | 
|---|
|  | 319 | "pic", | 
|---|
|  | 320 | (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
|  | 321 | &chdev_inode_xp ); | 
|---|
|  | 322 |  | 
|---|
|  | 323 | // create TXT chdev inodes | 
|---|
|  | 324 | for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ ) | 
|---|
|  | 325 | { | 
|---|
|  | 326 | chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.txt[channel] ); | 
|---|
|  | 327 | snprintf( node_name , 16 , "txt_%d" , channel ); | 
|---|
|  | 328 | devfs_register_chdev( chdev_ptr, | 
|---|
|  | 329 | node_name, | 
|---|
|  | 330 | (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
|  | 331 | &chdev_inode_xp ); | 
|---|
|  | 332 | } | 
|---|
|  | 333 |  | 
|---|
|  | 334 | // create IOC chdev inodes | 
|---|
|  | 335 | for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ ) | 
|---|
|  | 336 | { | 
|---|
|  | 337 | chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.ioc[channel] ); | 
|---|
|  | 338 | snprintf( node_name , 16 , "ioc_%d" , channel ); | 
|---|
|  | 339 | devfs_register_chdev( chdev_ptr, | 
|---|
|  | 340 | node_name, | 
|---|
|  | 341 | (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
|  | 342 | &chdev_inode_xp ); | 
|---|
|  | 343 | } | 
|---|
|  | 344 |  | 
|---|
|  | 345 | // create FBF chdev inodes | 
|---|
|  | 346 | for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ ) | 
|---|
|  | 347 | { | 
|---|
|  | 348 | chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.ioc[channel] ); | 
|---|
|  | 349 | snprintf( node_name , 16 , "fbf_%d" , channel ); | 
|---|
|  | 350 | devfs_register_chdev( chdev_ptr, | 
|---|
|  | 351 | node_name, | 
|---|
|  | 352 | (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
|  | 353 | &chdev_inode_xp ); | 
|---|
|  | 354 | } | 
|---|
|  | 355 |  | 
|---|
|  | 356 | // create NIC_RX chdevs | 
|---|
|  | 357 | for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) | 
|---|
|  | 358 | { | 
|---|
|  | 359 | chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.nic_rx[channel] ); | 
|---|
|  | 360 | snprintf( node_name , 16 , "nic_rx_%d" , channel ); | 
|---|
|  | 361 | devfs_register_chdev( chdev_ptr, | 
|---|
|  | 362 | node_name, | 
|---|
|  | 363 | (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
|  | 364 | &chdev_inode_xp ); | 
|---|
|  | 365 | } | 
|---|
|  | 366 |  | 
|---|
|  | 367 | // create NIC_TX chdev inodes | 
|---|
|  | 368 | for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ ) | 
|---|
|  | 369 | { | 
|---|
|  | 370 | chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.nic_tx[channel] ); | 
|---|
|  | 371 | snprintf( node_name , 16 , "nic_tx_%d" , channel ); | 
|---|
|  | 372 | devfs_register_chdev( chdev_ptr, | 
|---|
|  | 373 | node_name, | 
|---|
|  | 374 | (vfs_inode_t *)GET_PTR( external_inode_xp ), | 
|---|
|  | 375 | &chdev_inode_xp ); | 
|---|
|  | 376 | printk("\n    @@@ devfs_mount : 11 / name = %s\n", devfs_root_name ); | 
|---|
|  | 377 |  | 
|---|
|  | 378 | } | 
|---|
|  | 379 | } | 
|---|
|  | 380 |  | 
|---|
|  | 381 | // synchronize all clusters | 
|---|
|  | 382 | remote_barrier( barrier_xp , nb_clusters ); | 
|---|
|  | 383 |  | 
|---|
|  | 384 | return 0; | 
|---|
|  | 385 |  | 
|---|
|  | 386 | }  // end devfs_init() | 
|---|
|  | 387 |  | 
|---|
|  | 388 |  | 
|---|
|  | 389 | //////////////////////////////////////////// | 
|---|
|  | 390 | error_t devfs_ctx_init( vfs_ctx_t * vfs_ctx, | 
|---|
|  | 391 | xptr_t      root_inode_xp ) | 
|---|
|  | 392 | { | 
|---|
|  | 393 | vfs_ctx->type    = FS_TYPE_DEVFS; | 
|---|
|  | 394 | vfs_ctx->attr    = 0;                // not READ_ONLY / not SYNC | 
|---|
|  | 395 | vfs_ctx->count   = 0;                // unused for DEVFS | 
|---|
|  | 396 | vfs_ctx->blksize = 0;                // unused for DEVFS | 
|---|
|  | 397 | vfs_ctx->root_xp = root_inode_xp; | 
|---|
|  | 398 | vfs_ctx->extend  = NULL;             // unused for DEVFS | 
|---|
|  | 399 |  | 
|---|
|  | 400 | spinlock_init( &vfs_ctx->lock ); | 
|---|
|  | 401 |  | 
|---|
|  | 402 | bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES ); | 
|---|
|  | 403 |  | 
|---|
|  | 404 | return 0; | 
|---|
|  | 405 | } | 
|---|
|  | 406 |  | 
|---|
|  | 407 |  | 
|---|
|  | 408 | //////////////////////////////////////////////////// | 
|---|
|  | 409 | error_t devfs_inode_create( vfs_inode_t * vfs_inode, | 
|---|
|  | 410 | chdev_t     * chdev ) | 
|---|
|  | 411 | { | 
|---|
|  | 412 | kmem_req_t      req; | 
|---|
|  | 413 | devfs_inode_t * devfs_inode; | 
|---|
|  | 414 |  | 
|---|
|  | 415 | // allocate memory for FATFS inode extension | 
|---|
|  | 416 | req.type    = KMEM_DEVFS_INODE; | 
|---|
|  | 417 | req.size    = sizeof(devfs_inode_t); | 
|---|
|  | 418 | req.flags   = AF_KERNEL | AF_ZERO; | 
|---|
|  | 419 | devfs_inode = (devfs_inode_t *)kmem_alloc( &req ); | 
|---|
|  | 420 |  | 
|---|
|  | 421 | if( devfs_inode == NULL ) return ENOMEM; | 
|---|
|  | 422 |  | 
|---|
|  | 423 | // link DEVFS inode to VFS inode | 
|---|
|  | 424 | vfs_inode->extend = devfs_inode; | 
|---|
|  | 425 |  | 
|---|
|  | 426 | // initialise DEVFS inode | 
|---|
|  | 427 | devfs_inode->chdev = chdev; | 
|---|
|  | 428 |  | 
|---|
|  | 429 | return 0; | 
|---|
|  | 430 | } | 
|---|
|  | 431 |  | 
|---|
|  | 432 | /////////////////////////////////////////////////// | 
|---|
|  | 433 | void devfs_inode_destroy( vfs_inode_t * vfs_inode ) | 
|---|
|  | 434 | { | 
|---|
|  | 435 | kmem_req_t      req; | 
|---|
|  | 436 | devfs_inode_t * devfs_inode; | 
|---|
|  | 437 |  | 
|---|
|  | 438 | // get pointer on DEVFS inode | 
|---|
|  | 439 | devfs_inode = (devfs_inode_t *)vfs_inode->extend; | 
|---|
|  | 440 |  | 
|---|
|  | 441 | req.type = KMEM_DEVFS_INODE; | 
|---|
|  | 442 | req.ptr  = devfs_inode; | 
|---|
|  | 443 | kmem_free( &req ); | 
|---|
|  | 444 |  | 
|---|
|  | 445 | vfs_inode->extend = NULL; | 
|---|
|  | 446 | } | 
|---|
|  | 447 |  | 
|---|
|  | 448 |  | 
|---|
|  | 449 | /* deprecated [AG] | 
|---|
|  | 450 |  | 
|---|
|  | 451 | error_t devfs_open_file( vfs_file_t * file, | 
|---|
|  | 452 | void       * extend ); | 
|---|
|  | 453 | { | 
|---|
|  | 454 | error_t err; | 
|---|
|  | 455 | register struct devfs_context_s *ctx; | 
|---|
|  | 456 | register struct devfs_file_s *info; | 
|---|
|  | 457 | chdev_t       * chdev; | 
|---|
|  | 458 | vfs_inode_t   * inode; | 
|---|
|  | 459 | dev_request_t   rq; | 
|---|
|  | 460 | kmem_req_t      req; | 
|---|
|  | 461 |  | 
|---|
|  | 462 | inode = file->inode; | 
|---|
|  | 463 |  | 
|---|
|  | 464 | info = file->fr_pv; | 
|---|
|  | 465 | ctx  = (struct devfs_context_s *)&inode->i_ctx->ctx_devfs; | 
|---|
|  | 466 |  | 
|---|
|  | 467 | if(!(inode->i_attr & VFS_DIR)) | 
|---|
|  | 468 | { | 
|---|
|  | 469 | dev = (struct device_s*)inode->i_pv; | 
|---|
|  | 470 |  | 
|---|
|  | 471 | if(dev->type == DEV_INTERNAL) | 
|---|
|  | 472 | return EPERM; | 
|---|
|  | 473 |  | 
|---|
|  | 474 | if(dev->type == DEV_BLK) | 
|---|
|  | 475 | VFS_SET(inode->i_attr,VFS_DEV_BLK); | 
|---|
|  | 476 | else | 
|---|
|  | 477 | VFS_SET(inode->i_attr,VFS_DEV_CHR); | 
|---|
|  | 478 |  | 
|---|
|  | 479 | if(dev->op.dev.open != NULL) | 
|---|
|  | 480 | { | 
|---|
|  | 481 | rq.fremote = file; | 
|---|
|  | 482 | if((err=dev->op.dev.open(dev, &rq))) | 
|---|
|  | 483 | return err; | 
|---|
|  | 484 | } | 
|---|
|  | 485 |  | 
|---|
|  | 486 | priv->dev = (void*)dev; | 
|---|
|  | 487 |  | 
|---|
|  | 488 | return 0; | 
|---|
|  | 489 | } | 
|---|
|  | 490 |  | 
|---|
|  | 491 | if(info == NULL) | 
|---|
|  | 492 | { | 
|---|
|  | 493 | req.type  = KMEM_DEVFS_FILE; | 
|---|
|  | 494 | req.size  = sizeof(*info); | 
|---|
|  | 495 | req.flags = AF_KERNEL; | 
|---|
|  | 496 | info      = kmem_alloc(&req); | 
|---|
|  | 497 | } | 
|---|
|  | 498 |  | 
|---|
|  | 499 | if(info == NULL) return ENOMEM; | 
|---|
|  | 500 |  | 
|---|
|  | 501 | metafs_iter_init(&devfs_db.root, &info->iter); | 
|---|
|  | 502 | info->ctx  = ctx; | 
|---|
|  | 503 | file->fr_pv = info; | 
|---|
|  | 504 |  | 
|---|
|  | 505 | metafs_print(&devfs_db.root); | 
|---|
|  | 506 | return 0; | 
|---|
|  | 507 | } | 
|---|
|  | 508 |  | 
|---|
|  | 509 | #define TMP_BUFF_SZ 512 | 
|---|
|  | 510 |  | 
|---|
|  | 511 | //FIXME: | 
|---|
|  | 512 | //add a "while" loop for the case where the | 
|---|
|  | 513 | //buffer TMP_BUFF_SZ is smaller than | 
|---|
|  | 514 | //buffer->size | 
|---|
|  | 515 | ////////////////////////////// | 
|---|
|  | 516 | devfs_read( vfs_file_t * file, | 
|---|
|  | 517 | char       * buffer ) | 
|---|
|  | 518 | { | 
|---|
|  | 519 | chdev_t       * chdev; | 
|---|
|  | 520 | dev_request_t   rq; | 
|---|
|  | 521 | uint32_t        count; | 
|---|
|  | 522 | uint8_t         buff[TMP_BUFF_SZ]; | 
|---|
|  | 523 |  | 
|---|
|  | 524 | // get pointer on chdev | 
|---|
|  | 525 | chdev = (chdev_t *)file->extend; | 
|---|
|  | 526 |  | 
|---|
|  | 527 | if( chdev->func == DEV_FUNC_TXT ) | 
|---|
|  | 528 | { | 
|---|
|  | 529 | } | 
|---|
|  | 530 | if( chdev->func == DEV_FUNC_IOC ) | 
|---|
|  | 531 | { | 
|---|
|  | 532 | } | 
|---|
|  | 533 | else | 
|---|
|  | 534 | { | 
|---|
|  | 535 | printk("\n[PANIC] in %s : illegal device functionnal type | 
|---|
|  | 536 |  | 
|---|
|  | 537 | rq.dst   = &buff[0]; | 
|---|
|  | 538 | rq.count = TMP_BUFF_SZ; | 
|---|
|  | 539 | rq.flags = 0; | 
|---|
|  | 540 | rq.file  = file; | 
|---|
|  | 541 |  | 
|---|
|  | 542 | if((count = dev->op.dev.read(dev, &rq)) < 0) | 
|---|
|  | 543 | return count; | 
|---|
|  | 544 |  | 
|---|
|  | 545 | buffer->scpy_to_buff(buffer, &buff[0], count); | 
|---|
|  | 546 | return count; | 
|---|
|  | 547 | } | 
|---|
|  | 548 |  | 
|---|
|  | 549 | //FIXME: To improve this an avoid the extra copy, | 
|---|
|  | 550 | //we could set along with the buffer(src and dest) | 
|---|
|  | 551 | //the functions to manipulate them, such as in | 
|---|
|  | 552 | //do_exec.c | 
|---|
|  | 553 | /////////////////////////////// | 
|---|
|  | 554 | devfs_write( vfs_file_t * file, | 
|---|
|  | 555 | char       * buffer ) | 
|---|
|  | 556 | { | 
|---|
|  | 557 | register struct device_s *dev; | 
|---|
|  | 558 | uint8_t buff[TMP_BUFF_SZ]; | 
|---|
|  | 559 | dev_request_t rq; | 
|---|
|  | 560 |  | 
|---|
|  | 561 | dev = (struct device_s*)file->f_private.dev; | 
|---|
|  | 562 |  | 
|---|
|  | 563 | //FIXME avoid the extra copy ? | 
|---|
|  | 564 | buffer->scpy_from_buff(buffer, (void*)&buff[0], TMP_BUFF_SZ); | 
|---|
|  | 565 | rq.src   = (void*)&buff[0]; | 
|---|
|  | 566 | rq.count = buffer->size; | 
|---|
|  | 567 | rq.flags = 0; | 
|---|
|  | 568 | rq.file  = file; | 
|---|
|  | 569 |  | 
|---|
|  | 570 | return dev->op.dev.write(dev, &rq); | 
|---|
|  | 571 | } | 
|---|
|  | 572 |  | 
|---|
|  | 573 | VFS_LSEEK_FILE(devfs_lseek) | 
|---|
|  | 574 | { | 
|---|
|  | 575 | register struct device_s *dev; | 
|---|
|  | 576 | dev_request_t rq; | 
|---|
|  | 577 |  | 
|---|
|  | 578 | dev = (struct device_s*)file->fr_inode->i_pv; | 
|---|
|  | 579 |  | 
|---|
|  | 580 | if(dev->op.dev.lseek == NULL) | 
|---|
|  | 581 | return VFS_ENOTUSED; | 
|---|
|  | 582 |  | 
|---|
|  | 583 | rq.fremote = file; | 
|---|
|  | 584 | return dev->op.dev.lseek(dev, &rq); | 
|---|
|  | 585 | } | 
|---|
|  | 586 |  | 
|---|
|  | 587 | VFS_CLOSE_FILE(devfs_close) | 
|---|
|  | 588 | { | 
|---|
|  | 589 | register struct device_s *dev; | 
|---|
|  | 590 | dev_request_t rq; | 
|---|
|  | 591 |  | 
|---|
|  | 592 | if(file->fr_inode->i_attr & VFS_DIR) | 
|---|
|  | 593 | return 0; | 
|---|
|  | 594 |  | 
|---|
|  | 595 | dev = (struct device_s*)file->fr_inode->i_pv; | 
|---|
|  | 596 |  | 
|---|
|  | 597 | if(dev->op.dev.close == NULL) | 
|---|
|  | 598 | return 0; | 
|---|
|  | 599 |  | 
|---|
|  | 600 | rq.fremote = file; | 
|---|
|  | 601 | return dev->op.dev.close(dev, &rq); | 
|---|
|  | 602 | } | 
|---|
|  | 603 |  | 
|---|
|  | 604 | VFS_RELEASE_FILE(devfs_release) | 
|---|
|  | 605 | { | 
|---|
|  | 606 | kmem_req_t req; | 
|---|
|  | 607 |  | 
|---|
|  | 608 | if(file->fr_pv == NULL) | 
|---|
|  | 609 | return 0; | 
|---|
|  | 610 |  | 
|---|
|  | 611 | req.type = KMEM_DEVFS_FILE; | 
|---|
|  | 612 | req.ptr  = file->fr_pv; | 
|---|
|  | 613 | kmem_free(&req); | 
|---|
|  | 614 |  | 
|---|
|  | 615 | file->fr_pv = NULL; | 
|---|
|  | 616 | return 0; | 
|---|
|  | 617 | } | 
|---|
|  | 618 |  | 
|---|
|  | 619 | VFS_READ_DIR(devfs_readdir) | 
|---|
|  | 620 | { | 
|---|
|  | 621 | register struct devfs_file_s *info; | 
|---|
|  | 622 | register struct metafs_s *current; | 
|---|
|  | 623 | register struct device_s *current_dev; | 
|---|
|  | 624 |  | 
|---|
|  | 625 | info = file->fr_pv; | 
|---|
|  | 626 |  | 
|---|
|  | 627 | if(file->fr_pv == NULL) | 
|---|
|  | 628 | return ENOTDIR; | 
|---|
|  | 629 |  | 
|---|
|  | 630 | if((current = metafs_lookup_next(&devfs_db.root, &info->iter)) == NULL) | 
|---|
|  | 631 | return EEODIR; | 
|---|
|  | 632 |  | 
|---|
|  | 633 | current_dev    = metafs_container(current, struct device_s, node); | 
|---|
|  | 634 | dirent->u_attr = (current_dev->type == DEV_BLK) ? VFS_DEV_BLK : VFS_DEV_CHR; | 
|---|
|  | 635 |  | 
|---|
|  | 636 | strcpy((char*)dirent->u_name, metafs_get_name(current)); | 
|---|
|  | 637 |  | 
|---|
|  | 638 | dirent->u_ino = (uint_t) current_dev->base_paddr; | 
|---|
|  | 639 |  | 
|---|
|  | 640 | return 0; | 
|---|
|  | 641 | } | 
|---|
|  | 642 |  | 
|---|
|  | 643 | VFS_MMAP_FILE(devfs_mmap) | 
|---|
|  | 644 | { | 
|---|
|  | 645 | register struct device_s *dev; | 
|---|
|  | 646 | dev_request_t rq; | 
|---|
|  | 647 |  | 
|---|
|  | 648 | dev = (struct device_s*)file->f_private.dev; | 
|---|
|  | 649 |  | 
|---|
|  | 650 | if(dev->op.dev.mmap == NULL) | 
|---|
|  | 651 | return ENODEV; | 
|---|
|  | 652 |  | 
|---|
|  | 653 | rq.flags  = 0; | 
|---|
|  | 654 | rq.file   = file; | 
|---|
|  | 655 | rq.region = region; | 
|---|
|  | 656 |  | 
|---|
|  | 657 | return dev->op.dev.mmap(dev, &rq); | 
|---|
|  | 658 | } | 
|---|
|  | 659 |  | 
|---|
|  | 660 | VFS_MMAP_FILE(devfs_munmap) | 
|---|
|  | 661 | { | 
|---|
|  | 662 | register struct device_s *dev; | 
|---|
|  | 663 | dev_request_t rq; | 
|---|
|  | 664 |  | 
|---|
|  | 665 | dev = (struct device_s*)file->f_private.dev; | 
|---|
|  | 666 |  | 
|---|
|  | 667 | if(dev->op.dev.munmap == NULL) | 
|---|
|  | 668 | return ENODEV; | 
|---|
|  | 669 |  | 
|---|
|  | 670 | rq.flags  = 0; | 
|---|
|  | 671 | rq.file   = file; | 
|---|
|  | 672 | rq.region = region; | 
|---|
|  | 673 |  | 
|---|
|  | 674 | return dev->op.dev.munmap(dev, &rq); | 
|---|
|  | 675 | } | 
|---|
|  | 676 |  | 
|---|
|  | 677 |  | 
|---|
|  | 678 | const struct vfs_file_op_s devfs_f_op = | 
|---|
|  | 679 | { | 
|---|
|  | 680 | .open    = devfs_open, | 
|---|
|  | 681 | .read    = devfs_read, | 
|---|
|  | 682 | .write   = devfs_write, | 
|---|
|  | 683 | .lseek   = devfs_lseek, | 
|---|
|  | 684 | .mmap    = devfs_mmap, | 
|---|
|  | 685 | .munmap  = devfs_munmap, | 
|---|
|  | 686 | .readdir = devfs_readdir, | 
|---|
|  | 687 | .close   = devfs_close, | 
|---|
|  | 688 | .release = devfs_release | 
|---|
|  | 689 | }; | 
|---|
|  | 690 |  | 
|---|
|  | 691 | */ | 
|---|
|  | 692 |  | 
|---|
|  | 693 |  | 
|---|