URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [io/] [fileio/] [v2_0/] [src/] [devfs.cxx] - Rev 174
Compare with Previous | Blame | View Log
//========================================================================== // // devfs.cxx // // Fileio device filesystem // //========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. // // eCos 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; either version 2 or (at your option) any later version. // // eCos 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 eCos; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. // // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. // at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): nickg // Contributors: nickg // Date: 2000-05-25 // Purpose: Fileio device filesystem // Description: This file implements a simple filesystem that interfaces // to the existing device IO subsystem. // // // // //####DESCRIPTIONEND#### // //========================================================================== #include <pkgconf/hal.h> #include <pkgconf/kernel.h> #include <pkgconf/io_fileio.h> #include <cyg/kernel/ktypes.h> // base kernel types #include <cyg/infra/cyg_trac.h> // tracing macros #include <cyg/infra/cyg_ass.h> // assertion macros #include "fio.h" // Private header #include <cyg/io/devtab.h> // device subsystem #include <cyg/io/config_keys.h> // CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN //========================================================================== // Forward definitions // Filesystem operations static int dev_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte ); static int dev_umount ( cyg_mtab_entry *mte ); static int dev_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int mode, cyg_file *fte ); static int dev_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ); static int dev_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ); static int dev_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ); static int dev_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2 ); static int dev_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2, int type ); static int dev_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_file *fte ); static int dev_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_dir *dir_out ); static int dev_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, struct stat *buf); static int dev_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len ); static int dev_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len ); // File operations static int dev_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); static int dev_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); static int dev_fo_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence ); static int dev_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, CYG_ADDRWORD data); static int dev_fo_select (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info); static int dev_fo_fsync (struct CYG_FILE_TAG *fp, int mode ); static int dev_fo_close (struct CYG_FILE_TAG *fp); static int dev_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf ); static int dev_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ); static int dev_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ); //========================================================================== // Filesystem table entries FSTAB_ENTRY( dev_fste, "devfs", 0, CYG_SYNCMODE_NONE, // dev system has its own sync mechanism dev_mount, dev_umount, dev_open, dev_unlink, dev_mkdir, dev_rmdir, dev_rename, dev_link, dev_opendir, dev_chdir, dev_stat, dev_getinfo, dev_setinfo); MTAB_ENTRY( dev_mte, "/dev", "devfs", "", 0); static cyg_fileops dev_fileops = { dev_fo_read, dev_fo_write, dev_fo_lseek, dev_fo_ioctl, dev_fo_select, dev_fo_fsync, dev_fo_close, dev_fo_fstat, dev_fo_getinfo, dev_fo_setinfo }; //========================================================================== // Filesystem operations // ------------------------------------------------------------------------- static int dev_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte ) { // Nothing to do here. The device IO subsystem has already initialized // iteslf, and the fileio infrastructure will do the rest. return 0; } // ------------------------------------------------------------------------- static int dev_umount ( cyg_mtab_entry *mte ) { // Nothing to do here. return 0; } // ------------------------------------------------------------------------- static int dev_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int mode, cyg_file *file ) { Cyg_ErrNo err; cyg_io_handle_t handle; // The name we are passed will point to the first character after // "/dev/". We know that the full string contains the prefix string, // so we back the pointer up by 5 chars. // A better approach would be for the device table entries to only // contain the part of the string after the prefix. name -= 5; err = cyg_io_lookup( name, &handle ); if( err < 0 ) return -err; // If we want non-blocking mode, configure the device for it. if( (mode & (O_NONBLOCK|O_RDONLY)) == (O_NONBLOCK|O_RDONLY) ) { cyg_uint32 f = 0; cyg_uint32 fsize = sizeof(f); err = cyg_io_set_config( handle, CYG_IO_SET_CONFIG_READ_BLOCKING, (void *)&f, &fsize); if( err < 0 ) return -err; } if( (mode & (O_NONBLOCK|O_WRONLY)) == (O_NONBLOCK|O_WRONLY) ) { cyg_uint32 f = 0; cyg_uint32 fsize = sizeof(f); err = cyg_io_set_config( handle, CYG_IO_SET_CONFIG_WRITE_BLOCKING, (void *)&f, &fsize); if( err < 0 ) return -err; } // Initialize the file object file->f_flag |= mode & CYG_FILE_MODE_MASK; file->f_type = CYG_FILE_TYPE_FILE; file->f_ops = &dev_fileops; file->f_offset = 0; file->f_data = (CYG_ADDRWORD)handle; file->f_xops = 0; return 0; } // ------------------------------------------------------------------------- static int dev_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ) { return EROFS; } // ------------------------------------------------------------------------- static int dev_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ) { return EROFS; } // ------------------------------------------------------------------------- static int dev_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ) { return EROFS; } // ------------------------------------------------------------------------- static int dev_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2 ) { return EROFS; } // ------------------------------------------------------------------------- static int dev_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2, int type ) { return EROFS; } // ------------------------------------------------------------------------- static int dev_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_file *fte ) { return ENOTDIR; } // ------------------------------------------------------------------------- static int dev_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_dir *dir_out ) { return ENOTDIR; } // ------------------------------------------------------------------------- static int dev_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, struct stat *buf) { Cyg_ErrNo err; cyg_io_handle_t handle; name -= 5; // See comment in dev_open() err = cyg_io_lookup( name, &handle ); if( err < 0 ) return -err; // Just fill in the stat buffer with some constant values. // FIXME: change this when block devices are available buf->st_mode = __stat_mode_CHR; buf->st_ino = (ino_t)handle; // map dev handle to inode buf->st_dev = 0; // (dev_t)handle; // same with dev id buf->st_nlink = 0; buf->st_uid = 0; buf->st_gid = 0; buf->st_size = 0; buf->st_atime = 0; buf->st_mtime = 0; buf->st_ctime = 0; return ENOERR; } // ------------------------------------------------------------------------- static int dev_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len ) { return ENOSYS; } // ------------------------------------------------------------------------- static int dev_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len ) { return ENOSYS; } //========================================================================== // File operations // ------------------------------------------------------------------------- static int dev_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) { Cyg_ErrNo err = 0; int i; // Now loop over the iovecs until they are all done, or // we get an error. for( i = 0; i < uio->uio_iovcnt; i++ ) { cyg_iovec *iov = &uio->uio_iov[i]; cyg_uint32 len = iov->iov_len; cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)fp->f_data; if (t->status & CYG_DEVTAB_STATUS_BLOCK) err = cyg_io_bread( (cyg_io_handle_t)t, iov->iov_base, &len, fp->f_offset); else err = cyg_io_read( (cyg_io_handle_t)t, iov->iov_base, &len); if( -EAGAIN == err ) // must be in non-blocking mode { uio->uio_resid -= len; return ENOERR; } if( err < 0 ) break; uio->uio_resid -= len; } return -err; } // ------------------------------------------------------------------------- static int dev_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) { Cyg_ErrNo err = 0; int i; // Now loop over the iovecs until they are all done, or // we get an error. for( i = 0; i < uio->uio_iovcnt; i++ ) { cyg_iovec *iov = &uio->uio_iov[i]; cyg_uint32 len = iov->iov_len; cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)fp->f_data; if (t->status & CYG_DEVTAB_STATUS_BLOCK) err = cyg_io_bwrite( (cyg_io_handle_t)t, iov->iov_base, &len, fp->f_offset); else err = cyg_io_write( (cyg_io_handle_t)t, iov->iov_base, &len); if( -EAGAIN == err ) // must be in non-blocking mode { uio->uio_resid -= len; return ENOERR; } if( err < 0 ) break; uio->uio_resid -= len; } return -err; } // ------------------------------------------------------------------------- static int dev_fo_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence ) { // All current devices have no notion of position. Just return zero // as the new position. *pos = 0; return ENOERR; } // ------------------------------------------------------------------------- static int dev_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, CYG_ADDRWORD data) { return ENOSYS; } // ------------------------------------------------------------------------- static cyg_bool dev_fo_select (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info) { return cyg_io_select( (cyg_io_handle_t)fp->f_data, which, info); } // ------------------------------------------------------------------------- static int dev_fo_fsync (struct CYG_FILE_TAG *fp, int mode ) { Cyg_ErrNo err; err = cyg_io_get_config((cyg_io_handle_t)fp->f_data, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, NULL, NULL); return -err; } // ------------------------------------------------------------------------- static int dev_fo_close (struct CYG_FILE_TAG *fp) { return ENOERR; } // ------------------------------------------------------------------------- static int dev_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf ) { // Just fill in the stat buffer with some constant values. // FIXME: change this when block devices are available buf->st_mode = __stat_mode_CHR; buf->st_ino = (ino_t)fp->f_data; // map dev handle to inode buf->st_dev = (dev_t)fp->f_data; // same with dev id buf->st_nlink = 0; buf->st_uid = 0; buf->st_gid = 0; buf->st_size = 0; buf->st_atime = 0; buf->st_mtime = 0; buf->st_ctime = 0; return ENOERR; } // ------------------------------------------------------------------------- static int dev_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ) { Cyg_ErrNo err = 0; cyg_uint32 ll = len; err = cyg_io_get_config( (cyg_io_handle_t)fp->f_data, key, buf, &ll ); return -err; } // ------------------------------------------------------------------------- static int dev_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ) { Cyg_ErrNo err = 0; cyg_uint32 ll = len; err = cyg_io_set_config( (cyg_io_handle_t)fp->f_data, key, buf, &ll ); return -err; } // ------------------------------------------------------------------------- // EOF devfs.cxx