]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/io/fileio/v2_0/src/devfs.cxx
Initial revision
[karo-tx-redboot.git] / packages / io / fileio / v2_0 / src / devfs.cxx
1 //==========================================================================
2 //
3 //      devfs.cxx
4 //
5 //      Fileio device filesystem
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Gary Thomas
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
43 //
44 // Author(s):           nickg
45 // Contributors:        nickg, gthomas
46 // Date:                2000-05-25
47 // Purpose:             Fileio device filesystem
48 // Description:         This file implements a simple filesystem that interfaces
49 //                      to the existing device IO subsystem.
50 //                      
51 //              
52 //              
53 //
54 //####DESCRIPTIONEND####
55 //
56 //==========================================================================
57
58 #include <pkgconf/hal.h>
59 #include <pkgconf/io_fileio.h>
60
61 #include <cyg/infra/cyg_trac.h>        // tracing macros
62 #include <cyg/infra/cyg_ass.h>         // assertion macros
63
64 #include "fio.h"                       // Private header
65
66 #include <cyg/io/devtab.h>              // device subsystem
67 #include <cyg/io/config_keys.h>         // CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
68
69 //==========================================================================
70 // Forward definitions
71
72 // Filesystem operations
73 static int dev_mount    ( cyg_fstab_entry *fste, cyg_mtab_entry *mte );
74 static int dev_umount   ( cyg_mtab_entry *mte );
75 static int dev_open     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
76                           int mode,  cyg_file *fte );
77 static int dev_unlink   ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
78 static int dev_mkdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
79 static int dev_rmdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
80 static int dev_rename   ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
81                           cyg_dir dir2, const char *name2 );
82 static int dev_link     ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
83                           cyg_dir dir2, const char *name2, int type );
84 static int dev_opendir  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
85                           cyg_file *fte );
86 static int dev_chdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
87                           cyg_dir *dir_out );
88 static int dev_stat     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
89                           struct stat *buf);
90 static int dev_getinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
91                           int key, void *buf, int len );
92 static int dev_setinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
93                           int key, void *buf, int len );
94
95 // File operations
96 static int dev_fo_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
97 static int dev_fo_write     (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
98 static int dev_fo_lseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
99 static int dev_fo_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
100                              CYG_ADDRWORD data);
101 static cyg_bool dev_fo_select (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info);
102 static int dev_fo_fsync     (struct CYG_FILE_TAG *fp, int mode );        
103 static int dev_fo_close     (struct CYG_FILE_TAG *fp);
104 static int dev_fo_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf );
105 static int dev_fo_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
106 static int dev_fo_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
107
108
109 //==========================================================================
110 // Filesystem table entries
111
112 FSTAB_ENTRY( dev_fste, "devfs", 0,
113              CYG_SYNCMODE_NONE,         // dev system has its own sync mechanism
114              dev_mount,
115              dev_umount,
116              dev_open,
117              dev_unlink,
118              dev_mkdir,
119              dev_rmdir,
120              dev_rename,
121              dev_link,
122              dev_opendir,
123              dev_chdir,
124              dev_stat,
125              dev_getinfo,
126              dev_setinfo);
127
128 MTAB_ENTRY( dev_mte,
129                    "/dev",
130                    "devfs",
131                    "",
132                    0);
133
134 static cyg_fileops dev_fileops =
135 {
136     dev_fo_read,
137     dev_fo_write,
138     dev_fo_lseek,
139     dev_fo_ioctl,
140     dev_fo_select,
141     dev_fo_fsync,
142     dev_fo_close,
143     dev_fo_fstat,
144     dev_fo_getinfo,
145     dev_fo_setinfo
146 };
147
148 //==========================================================================
149 // Filesystem operations
150
151 // -------------------------------------------------------------------------
152
153 static int dev_mount    ( cyg_fstab_entry *fste, cyg_mtab_entry *mte )
154 {
155     // Nothing to do here. The device IO subsystem has already initialized
156     // iteslf, and the fileio infrastructure will do the rest.
157     
158     return 0;
159 }
160
161 // -------------------------------------------------------------------------
162
163 static int dev_umount   ( cyg_mtab_entry *mte )
164 {
165     // Nothing to do here.
166     
167     return 0;
168 }
169
170 // -------------------------------------------------------------------------
171
172 static int dev_open     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
173                           int mode,  cyg_file *file )
174 {
175     Cyg_ErrNo err;
176     cyg_io_handle_t handle;
177
178     // The name we are passed will point to the first character after
179     // "/dev/". We know that the full string contains the prefix string,
180     // so we back the pointer up by 5 chars.
181     // A better approach would be for the device table entries to only
182     // contain the part of the string after the prefix.
183
184     name -= 5;
185     
186     err = cyg_io_lookup( name, &handle );
187
188     if( err < 0 )
189         return -err;
190
191     // If we want non-blocking mode, configure the device for it.
192     if( (mode & (O_NONBLOCK|O_RDONLY)) == (O_NONBLOCK|O_RDONLY) )
193     {
194         cyg_uint32 f = 0;
195         cyg_uint32 fsize = sizeof(f);
196         err = cyg_io_set_config( handle, CYG_IO_SET_CONFIG_READ_BLOCKING,
197                                  (void *)&f, &fsize);
198         if( err < 0 )
199             return -err;
200     }
201
202     if( (mode & (O_NONBLOCK|O_WRONLY)) == (O_NONBLOCK|O_WRONLY) )
203     {
204         cyg_uint32 f = 0;
205         cyg_uint32 fsize = sizeof(f);        
206         err = cyg_io_set_config( handle, CYG_IO_SET_CONFIG_WRITE_BLOCKING,
207                                  (void *)&f, &fsize);
208         if( err < 0 )
209             return -err;
210     }
211     
212     // Initialize the file object
213     
214     file->f_flag |= mode & CYG_FILE_MODE_MASK;
215     file->f_type = CYG_FILE_TYPE_FILE;
216     file->f_ops = &dev_fileops;
217     file->f_offset = 0;
218     file->f_data = (CYG_ADDRWORD)handle;
219     file->f_xops = 0;
220
221     return 0;
222 }
223
224 // -------------------------------------------------------------------------
225
226 static int dev_unlink   ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
227 {
228     return EROFS;
229 }
230
231 // -------------------------------------------------------------------------
232
233 static int dev_mkdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
234 {
235     return EROFS;
236 }
237
238 // -------------------------------------------------------------------------
239
240 static int dev_rmdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
241 {
242     return EROFS;
243 }
244
245 // -------------------------------------------------------------------------
246
247 static int dev_rename   ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
248                           cyg_dir dir2, const char *name2 )
249 {
250     return EROFS;
251 }
252
253 // -------------------------------------------------------------------------
254
255 static int dev_link     ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
256                           cyg_dir dir2, const char *name2, int type )
257 {
258     return EROFS;
259 }
260
261 // -------------------------------------------------------------------------
262
263 static int dev_opendir  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
264                           cyg_file *fte )
265 {
266     return ENOTDIR;
267 }
268
269 // -------------------------------------------------------------------------
270
271 static int dev_chdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
272                           cyg_dir *dir_out )
273 {
274     return ENOTDIR;
275 }
276
277 // -------------------------------------------------------------------------
278
279 static int dev_stat     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
280                           struct stat *buf)
281 {
282     Cyg_ErrNo err;
283     cyg_io_handle_t handle;
284     cyg_devtab_entry_t *dev;
285
286     name -= 5;          // See comment in dev_open()
287     
288     err = cyg_io_lookup( name, &handle );
289
290     if( err < 0 )
291         return -err;
292
293     // Just fill in the stat buffer with some constant values.
294     dev = (cyg_devtab_entry_t *)handle;
295
296     if (dev->status & CYG_DEVTAB_STATUS_BLOCK)
297         buf->st_mode = __stat_mode_BLK;
298     else
299         buf->st_mode = __stat_mode_CHR;
300
301     buf->st_ino         = (ino_t)handle;    // map dev handle to inode
302     buf->st_dev         = 0; // (dev_t)handle;    // same with dev id
303     buf->st_nlink       = 1;
304     buf->st_uid         = 0;
305     buf->st_gid         = 0;
306     buf->st_size        = 0;
307     buf->st_atime       = 0;
308     buf->st_mtime       = 0;
309     buf->st_ctime       = 0;
310     
311     return ENOERR;
312 }
313
314 // -------------------------------------------------------------------------
315
316 static int dev_getinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
317                           int key, void *buf, int len )
318 {
319     return ENOSYS;
320 }
321
322 // -------------------------------------------------------------------------
323
324 static int dev_setinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
325                           int key, void *buf, int len )
326 {
327     return ENOSYS;
328 }
329
330 //==========================================================================
331 // File operations
332
333
334 // -------------------------------------------------------------------------
335
336 static int dev_fo_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
337 {
338     Cyg_ErrNo err = 0;
339     int i;
340
341     // Now loop over the iovecs until they are all done, or
342     // we get an error.
343     for( i = 0; i < uio->uio_iovcnt; i++ )
344     {
345         cyg_iovec *iov = &uio->uio_iov[i];
346         cyg_uint32 len = iov->iov_len;
347         cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)fp->f_data;    
348
349         if (t->status & CYG_DEVTAB_STATUS_BLOCK)
350             err = cyg_io_bread( (cyg_io_handle_t)t,
351                                 iov->iov_base,
352                                 &len, fp->f_offset);
353         else
354             err = cyg_io_read( (cyg_io_handle_t)t,
355                                iov->iov_base,
356                                &len);
357
358         if( err < 0 ) break;
359
360         uio->uio_resid -= len;
361     }
362     
363     return -err;
364 }
365
366 // -------------------------------------------------------------------------
367
368 static int dev_fo_write     (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
369 {
370     Cyg_ErrNo err = 0;
371     int i;
372
373     // Now loop over the iovecs until they are all done, or
374     // we get an error.
375     for( i = 0; i < uio->uio_iovcnt; i++ )
376     {
377         cyg_iovec *iov = &uio->uio_iov[i];
378         cyg_uint32 len = iov->iov_len;
379         cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)fp->f_data;
380
381         if (t->status & CYG_DEVTAB_STATUS_BLOCK)  
382             err = cyg_io_bwrite( (cyg_io_handle_t)t,
383                                  iov->iov_base,
384                                  &len, fp->f_offset);
385         else
386             err = cyg_io_write( (cyg_io_handle_t)t,
387                                 iov->iov_base,
388                                 &len);
389
390         if( err < 0 ) break;
391
392         uio->uio_resid -= len;
393     }
394
395     return -err;
396 }
397
398 // -------------------------------------------------------------------------
399
400 static int dev_fo_lseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence )
401 {
402     // All current devices have no notion of position. Just return zero
403     // as the new position.
404
405     *pos = 0;
406     
407     return ENOERR;
408 }
409
410 // -------------------------------------------------------------------------
411
412 static int dev_fo_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
413                              CYG_ADDRWORD data)
414 {
415     return ENOSYS;
416 }
417
418 // -------------------------------------------------------------------------
419
420 static cyg_bool dev_fo_select    (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info)
421 {
422     return cyg_io_select( (cyg_io_handle_t)fp->f_data,
423                           which,
424                           info);
425 }
426
427 // -------------------------------------------------------------------------
428
429 static int dev_fo_fsync     (struct CYG_FILE_TAG *fp, int mode )
430 {
431     Cyg_ErrNo err;
432
433     err = cyg_io_get_config((cyg_io_handle_t)fp->f_data,
434                             CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN,
435                             NULL, NULL);
436
437     return -err;
438 }
439
440 // -------------------------------------------------------------------------
441
442 static int dev_fo_close     (struct CYG_FILE_TAG *fp)
443 {
444     return ENOERR;
445 }
446
447 // -------------------------------------------------------------------------
448
449 static int dev_fo_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf )
450 {
451     cyg_devtab_entry_t *dev = (cyg_devtab_entry_t *)fp->f_data;
452
453     // Just fill in the stat buffer with some constant values.
454     if (dev->status & CYG_DEVTAB_STATUS_BLOCK)
455         buf->st_mode = __stat_mode_BLK;
456     else
457         buf->st_mode = __stat_mode_CHR;
458
459     buf->st_ino         = (ino_t)fp->f_data;    // map dev handle to inode
460     buf->st_dev         = 0;   //(dev_t)fp->f_data;    // same with dev id
461     buf->st_nlink       = 1;
462     buf->st_uid         = 0;
463     buf->st_gid         = 0;
464     buf->st_size        = 0;
465     buf->st_atime       = 0;
466     buf->st_mtime       = 0;
467     buf->st_ctime       = 0;
468     
469     return ENOERR;
470 }
471
472 // -------------------------------------------------------------------------
473
474 static int dev_fo_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
475 {
476     Cyg_ErrNo err = 0;
477     cyg_uint32 ll = len;
478     
479     err = cyg_io_get_config( (cyg_io_handle_t)fp->f_data, key, buf, &ll );
480     
481     return -err;
482 }
483
484 // -------------------------------------------------------------------------
485
486 static int dev_fo_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
487 {
488     Cyg_ErrNo err = 0;
489     cyg_uint32 ll = len;
490     
491     err = cyg_io_set_config( (cyg_io_handle_t)fp->f_data, key, buf, &ll );
492     
493     return -err;
494 }
495
496 // -------------------------------------------------------------------------
497 // EOF devfs.cxx