OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [proc/] [scsi.c] - Diff between revs 1628 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 1628 Rev 1765
/*
/*
 *  linux/fs/proc/scsi.c
 *  linux/fs/proc/scsi.c
 *  (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de
 *  (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de
 *
 *
 *  The original version was derived from linux/fs/proc/net.c,
 *  The original version was derived from linux/fs/proc/net.c,
 *  which is Copyright (C) 1991, 1992 Linus Torvalds.
 *  which is Copyright (C) 1991, 1992 Linus Torvalds.
 *  Much has been rewritten, but some of the code still remains.
 *  Much has been rewritten, but some of the code still remains.
 *
 *
 *  /proc/scsi directory handling functions
 *  /proc/scsi directory handling functions
 *
 *
 *  last change: 95/07/04
 *  last change: 95/07/04
 *
 *
 *  Initial version: March '95
 *  Initial version: March '95
 *  95/05/15 Added subdirectories for each driver and show every
 *  95/05/15 Added subdirectories for each driver and show every
 *           registered HBA as a single file.
 *           registered HBA as a single file.
 *  95/05/30 Added rudimentary write support for parameter passing
 *  95/05/30 Added rudimentary write support for parameter passing
 *  95/07/04 Fixed bugs in directory handling
 *  95/07/04 Fixed bugs in directory handling
 *  95/09/13 Update to support the new proc-dir tree
 *  95/09/13 Update to support the new proc-dir tree
 *
 *
 *  TODO: Improve support to write to the driver files
 *  TODO: Improve support to write to the driver files
 *        Add some more comments
 *        Add some more comments
 */
 */
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/mm.h>
 
 
#include <asm/segment.h>
#include <asm/segment.h>
 
 
/* forward references */
/* forward references */
static int proc_readscsi(struct inode * inode, struct file * file,
static int proc_readscsi(struct inode * inode, struct file * file,
                         char * buf, int count);
                         char * buf, int count);
static int proc_writescsi(struct inode * inode, struct file * file,
static int proc_writescsi(struct inode * inode, struct file * file,
                         const char * buf, int count);
                         const char * buf, int count);
static int proc_scsilseek(struct inode *, struct file *, off_t, int);
static int proc_scsilseek(struct inode *, struct file *, off_t, int);
 
 
extern void build_proc_dir_hba_entries(uint);
extern void build_proc_dir_hba_entries(uint);
 
 
/* the *_get_info() functions are in the respective scsi driver code */
/* the *_get_info() functions are in the respective scsi driver code */
int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
                                off_t offset, int length, int inout) = 0;
                                off_t offset, int length, int inout) = 0;
 
 
static struct file_operations proc_scsi_operations = {
static struct file_operations proc_scsi_operations = {
    proc_scsilseek,     /* lseek   */
    proc_scsilseek,     /* lseek   */
    proc_readscsi,      /* read    */
    proc_readscsi,      /* read    */
    proc_writescsi,     /* write   */
    proc_writescsi,     /* write   */
    proc_readdir,       /* readdir */
    proc_readdir,       /* readdir */
    NULL,               /* select  */
    NULL,               /* select  */
    NULL,               /* ioctl   */
    NULL,               /* ioctl   */
    NULL,               /* mmap    */
    NULL,               /* mmap    */
    NULL,               /* no special open code    */
    NULL,               /* no special open code    */
    NULL,               /* no special release code */
    NULL,               /* no special release code */
    NULL                /* can't fsync */
    NULL                /* can't fsync */
};
};
 
 
/*
/*
 * proc directories can do almost nothing..
 * proc directories can do almost nothing..
 */
 */
struct inode_operations proc_scsi_inode_operations = {
struct inode_operations proc_scsi_inode_operations = {
    &proc_scsi_operations,  /* default scsi directory file-ops */
    &proc_scsi_operations,  /* default scsi directory file-ops */
    NULL,           /* create      */
    NULL,           /* create      */
    proc_lookup,    /* lookup      */
    proc_lookup,    /* lookup      */
    NULL,           /* link        */
    NULL,           /* link        */
    NULL,           /* unlink      */
    NULL,           /* unlink      */
    NULL,           /* symlink     */
    NULL,           /* symlink     */
    NULL,           /* mkdir       */
    NULL,           /* mkdir       */
    NULL,           /* rmdir       */
    NULL,           /* rmdir       */
    NULL,           /* mknod       */
    NULL,           /* mknod       */
    NULL,           /* rename      */
    NULL,           /* rename      */
    NULL,           /* readlink    */
    NULL,           /* readlink    */
    NULL,           /* follow_link */
    NULL,           /* follow_link */
    NULL,           /* readpage    */
    NULL,           /* readpage    */
    NULL,           /* writepage   */
    NULL,           /* writepage   */
    NULL,           /* bmap        */
    NULL,           /* bmap        */
    NULL,           /* truncate    */
    NULL,           /* truncate    */
    NULL            /* permission  */
    NULL            /* permission  */
};
};
 
 
int get_not_present_info(char *buffer, char **start, off_t offset, int length)
int get_not_present_info(char *buffer, char **start, off_t offset, int length)
{
{
    int len, pos, begin;
    int len, pos, begin;
 
 
    begin = 0;
    begin = 0;
    pos = len = sprintf(buffer,
    pos = len = sprintf(buffer,
                        "No low-level scsi modules are currently present\n");
                        "No low-level scsi modules are currently present\n");
    if(pos < offset) {
    if(pos < offset) {
        len = 0;
        len = 0;
        begin = pos;
        begin = pos;
    }
    }
 
 
    *start = buffer + (offset - begin);   /* Start of wanted data */
    *start = buffer + (offset - begin);   /* Start of wanted data */
    len -= (offset - begin);
    len -= (offset - begin);
    if(len > length)
    if(len > length)
        len = length;
        len = length;
 
 
    return(len);
    return(len);
}
}
 
 
#define PROC_BLOCK_SIZE (3*1024)     /* 4K page size, but our output routines 
#define PROC_BLOCK_SIZE (3*1024)     /* 4K page size, but our output routines 
                                      * use some slack for overruns
                                      * use some slack for overruns
                                      */
                                      */
 
 
static int proc_readscsi(struct inode * inode, struct file * file,
static int proc_readscsi(struct inode * inode, struct file * file,
                         char * buf, int count)
                         char * buf, int count)
{
{
    int length;
    int length;
    int bytes = count;
    int bytes = count;
    int copied = 0;
    int copied = 0;
    int thistime;
    int thistime;
    char * page;
    char * page;
    char * start;
    char * start;
 
 
    if (count < -1)               /* Normally I wouldn't do this, */
    if (count < -1)               /* Normally I wouldn't do this, */
        return(-EINVAL);          /* but it saves some redundant code.
        return(-EINVAL);          /* but it saves some redundant code.
                                   * Now it is possible to seek to the
                                   * Now it is possible to seek to the
                                   * end of the file */
                                   * end of the file */
    if (!(page = (char *) __get_free_page(GFP_KERNEL)))
    if (!(page = (char *) __get_free_page(GFP_KERNEL)))
        return(-ENOMEM);
        return(-ENOMEM);
 
 
    while(bytes > 0 || count == -1) {
    while(bytes > 0 || count == -1) {
        thistime = bytes;
        thistime = bytes;
        if(bytes > PROC_BLOCK_SIZE || count == -1)
        if(bytes > PROC_BLOCK_SIZE || count == -1)
            thistime = PROC_BLOCK_SIZE;
            thistime = PROC_BLOCK_SIZE;
 
 
        if(dispatch_scsi_info_ptr)
        if(dispatch_scsi_info_ptr)
            length = dispatch_scsi_info_ptr(inode->i_ino, page, &start,
            length = dispatch_scsi_info_ptr(inode->i_ino, page, &start,
                                            file->f_pos, thistime, 0);
                                            file->f_pos, thistime, 0);
        else
        else
            length = get_not_present_info(page, &start, file->f_pos, thistime);
            length = get_not_present_info(page, &start, file->f_pos, thistime);
        if(length < 0) {
        if(length < 0) {
            free_page((ulong) page);
            free_page((ulong) page);
            return(length);
            return(length);
        }
        }
 
 
        /*
        /*
         *  We have been given a non page aligned block of
         *  We have been given a non page aligned block of
         *  the data we asked for + a bit. We have been given
         *  the data we asked for + a bit. We have been given
         *  the start pointer and we know the length..
         *  the start pointer and we know the length..
         */
         */
        if (length <= 0)
        if (length <= 0)
            break;
            break;
        /*
        /*
         *  Copy the bytes, if we're not doing a seek to
         *  Copy the bytes, if we're not doing a seek to
         *      the end of the file
         *      the end of the file
         */
         */
        if (count != -1)
        if (count != -1)
            memcpy_tofs(buf + copied, start, length);
            memcpy_tofs(buf + copied, start, length);
        file->f_pos += length;  /* Move down the file */
        file->f_pos += length;  /* Move down the file */
        bytes -= length;
        bytes -= length;
        copied += length;
        copied += length;
 
 
        if(length < thistime)
        if(length < thistime)
            break;  /* End of file */
            break;  /* End of file */
 
 
    }
    }
 
 
    free_page((ulong) page);
    free_page((ulong) page);
    return(copied);
    return(copied);
}
}
 
 
 
 
static int proc_writescsi(struct inode * inode, struct file * file,
static int proc_writescsi(struct inode * inode, struct file * file,
                         const char * buf, int count)
                         const char * buf, int count)
{
{
    int ret = 0;
    int ret = 0;
    char * page;
    char * page;
 
 
    if(count > PROC_BLOCK_SIZE) {
    if(count > PROC_BLOCK_SIZE) {
        return(-EOVERFLOW);
        return(-EOVERFLOW);
    }
    }
 
 
    if(dispatch_scsi_info_ptr != NULL) {
    if(dispatch_scsi_info_ptr != NULL) {
        if (!(page = (char *) __get_free_page(GFP_KERNEL)))
        if (!(page = (char *) __get_free_page(GFP_KERNEL)))
            return(-ENOMEM);
            return(-ENOMEM);
        memcpy_fromfs(page, buf, count);
        memcpy_fromfs(page, buf, count);
        ret = dispatch_scsi_info_ptr(inode->i_ino, page, 0, 0, count, 1);
        ret = dispatch_scsi_info_ptr(inode->i_ino, page, 0, 0, count, 1);
    } else
    } else
        return(-ENOPKG);          /* Nothing here */
        return(-ENOPKG);          /* Nothing here */
 
 
    free_page((ulong) page);
    free_page((ulong) page);
    return(ret);
    return(ret);
}
}
 
 
 
 
static int proc_scsilseek(struct inode * inode, struct file * file,
static int proc_scsilseek(struct inode * inode, struct file * file,
                          off_t offset, int orig)
                          off_t offset, int orig)
{
{
    switch (orig) {
    switch (orig) {
    case 0:
    case 0:
        file->f_pos = offset;
        file->f_pos = offset;
        return(file->f_pos);
        return(file->f_pos);
    case 1:
    case 1:
        file->f_pos += offset;
        file->f_pos += offset;
        return(file->f_pos);
        return(file->f_pos);
    case 2:                  /* This ugly hack allows us to    */
    case 2:                  /* This ugly hack allows us to    */
        if (offset)          /* to determine the length of the */
        if (offset)          /* to determine the length of the */
            return(-EINVAL); /* file and then later safely to  */
            return(-EINVAL); /* file and then later safely to  */
        proc_readscsi(inode, file, 0, -1); /* seek in it       */
        proc_readscsi(inode, file, 0, -1); /* seek in it       */
        return(file->f_pos);
        return(file->f_pos);
    default:
    default:
        return(-EINVAL);
        return(-EINVAL);
    }
    }
}
}
 
 
/*
/*
 * Overrides for Emacs so that we almost follow Linus's tabbing style.
 * Overrides for Emacs so that we almost follow Linus's tabbing style.
 * Emacs will notice this stuff at the end of the file and automatically
 * Emacs will notice this stuff at the end of the file and automatically
 * adjust the settings for this buffer only.  This must remain at the end
 * adjust the settings for this buffer only.  This must remain at the end
 * of the file.
 * of the file.
 * ---------------------------------------------------------------------------
 * ---------------------------------------------------------------------------
 * Local variables:
 * Local variables:
 * c-indent-level: 4
 * c-indent-level: 4
 * c-brace-imaginary-offset: 0
 * c-brace-imaginary-offset: 0
 * c-brace-offset: -4
 * c-brace-offset: -4
 * c-argdecl-indent: 4
 * c-argdecl-indent: 4
 * c-label-offset: -4
 * c-label-offset: -4
 * c-continued-statement-offset: 4
 * c-continued-statement-offset: 4
 * c-continued-brace-offset: 0
 * c-continued-brace-offset: 0
 * indent-tabs-mode: nil
 * indent-tabs-mode: nil
 * tab-width: 8
 * tab-width: 8
 * End:
 * End:
 */
 */
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.