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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [proc/] [scsi.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/proc/scsi.c
3
 *  (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de
4
 *
5
 *  The original version was derived from linux/fs/proc/net.c,
6
 *  which is Copyright (C) 1991, 1992 Linus Torvalds.
7
 *  Much has been rewritten, but some of the code still remains.
8
 *
9
 *  /proc/scsi directory handling functions
10
 *
11
 *  last change: 95/07/04
12
 *
13
 *  Initial version: March '95
14
 *  95/05/15 Added subdirectories for each driver and show every
15
 *           registered HBA as a single file.
16
 *  95/05/30 Added rudimentary write support for parameter passing
17
 *  95/07/04 Fixed bugs in directory handling
18
 *  95/09/13 Update to support the new proc-dir tree
19
 *
20
 *  TODO: Improve support to write to the driver files
21
 *        Add some more comments
22
 */
23
#include <linux/errno.h>
24
#include <linux/sched.h>
25
#include <linux/proc_fs.h>
26
#include <linux/stat.h>
27
#include <linux/mm.h>
28
 
29
#include <asm/segment.h>
30
 
31
/* forward references */
32
static int proc_readscsi(struct inode * inode, struct file * file,
33
                         char * buf, int count);
34
static int proc_writescsi(struct inode * inode, struct file * file,
35
                         const char * buf, int count);
36
static int proc_scsilseek(struct inode *, struct file *, off_t, int);
37
 
38
extern void build_proc_dir_hba_entries(uint);
39
 
40
/* the *_get_info() functions are in the respective scsi driver code */
41
int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
42
                                off_t offset, int length, int inout) = 0;
43
 
44
static struct file_operations proc_scsi_operations = {
45
    proc_scsilseek,     /* lseek   */
46
    proc_readscsi,      /* read    */
47
    proc_writescsi,     /* write   */
48
    proc_readdir,       /* readdir */
49
    NULL,               /* select  */
50
    NULL,               /* ioctl   */
51
    NULL,               /* mmap    */
52
    NULL,               /* no special open code    */
53
    NULL,               /* no special release code */
54
    NULL                /* can't fsync */
55
};
56
 
57
/*
58
 * proc directories can do almost nothing..
59
 */
60
struct inode_operations proc_scsi_inode_operations = {
61
    &proc_scsi_operations,  /* default scsi directory file-ops */
62
    NULL,           /* create      */
63
    proc_lookup,    /* lookup      */
64
    NULL,           /* link        */
65
    NULL,           /* unlink      */
66
    NULL,           /* symlink     */
67
    NULL,           /* mkdir       */
68
    NULL,           /* rmdir       */
69
    NULL,           /* mknod       */
70
    NULL,           /* rename      */
71
    NULL,           /* readlink    */
72
    NULL,           /* follow_link */
73
    NULL,           /* readpage    */
74
    NULL,           /* writepage   */
75
    NULL,           /* bmap        */
76
    NULL,           /* truncate    */
77
    NULL            /* permission  */
78
};
79
 
80
int get_not_present_info(char *buffer, char **start, off_t offset, int length)
81
{
82
    int len, pos, begin;
83
 
84
    begin = 0;
85
    pos = len = sprintf(buffer,
86
                        "No low-level scsi modules are currently present\n");
87
    if(pos < offset) {
88
        len = 0;
89
        begin = pos;
90
    }
91
 
92
    *start = buffer + (offset - begin);   /* Start of wanted data */
93
    len -= (offset - begin);
94
    if(len > length)
95
        len = length;
96
 
97
    return(len);
98
}
99
 
100
#define PROC_BLOCK_SIZE (3*1024)     /* 4K page size, but our output routines 
101
                                      * use some slack for overruns
102
                                      */
103
 
104
static int proc_readscsi(struct inode * inode, struct file * file,
105
                         char * buf, int count)
106
{
107
    int length;
108
    int bytes = count;
109
    int copied = 0;
110
    int thistime;
111
    char * page;
112
    char * start;
113
 
114
    if (count < -1)               /* Normally I wouldn't do this, */
115
        return(-EINVAL);          /* but it saves some redundant code.
116
                                   * Now it is possible to seek to the
117
                                   * end of the file */
118
    if (!(page = (char *) __get_free_page(GFP_KERNEL)))
119
        return(-ENOMEM);
120
 
121
    while(bytes > 0 || count == -1) {
122
        thistime = bytes;
123
        if(bytes > PROC_BLOCK_SIZE || count == -1)
124
            thistime = PROC_BLOCK_SIZE;
125
 
126
        if(dispatch_scsi_info_ptr)
127
            length = dispatch_scsi_info_ptr(inode->i_ino, page, &start,
128
                                            file->f_pos, thistime, 0);
129
        else
130
            length = get_not_present_info(page, &start, file->f_pos, thistime);
131
        if(length < 0) {
132
            free_page((ulong) page);
133
            return(length);
134
        }
135
 
136
        /*
137
         *  We have been given a non page aligned block of
138
         *  the data we asked for + a bit. We have been given
139
         *  the start pointer and we know the length..
140
         */
141
        if (length <= 0)
142
            break;
143
        /*
144
         *  Copy the bytes, if we're not doing a seek to
145
         *      the end of the file
146
         */
147
        if (count != -1)
148
            memcpy_tofs(buf + copied, start, length);
149
        file->f_pos += length;  /* Move down the file */
150
        bytes -= length;
151
        copied += length;
152
 
153
        if(length < thistime)
154
            break;  /* End of file */
155
 
156
    }
157
 
158
    free_page((ulong) page);
159
    return(copied);
160
}
161
 
162
 
163
static int proc_writescsi(struct inode * inode, struct file * file,
164
                         const char * buf, int count)
165
{
166
    int ret = 0;
167
    char * page;
168
 
169
    if(count > PROC_BLOCK_SIZE) {
170
        return(-EOVERFLOW);
171
    }
172
 
173
    if(dispatch_scsi_info_ptr != NULL) {
174
        if (!(page = (char *) __get_free_page(GFP_KERNEL)))
175
            return(-ENOMEM);
176
        memcpy_fromfs(page, buf, count);
177
        ret = dispatch_scsi_info_ptr(inode->i_ino, page, 0, 0, count, 1);
178
    } else
179
        return(-ENOPKG);          /* Nothing here */
180
 
181
    free_page((ulong) page);
182
    return(ret);
183
}
184
 
185
 
186
static int proc_scsilseek(struct inode * inode, struct file * file,
187
                          off_t offset, int orig)
188
{
189
    switch (orig) {
190
    case 0:
191
        file->f_pos = offset;
192
        return(file->f_pos);
193
    case 1:
194
        file->f_pos += offset;
195
        return(file->f_pos);
196
    case 2:                  /* This ugly hack allows us to    */
197
        if (offset)          /* to determine the length of the */
198
            return(-EINVAL); /* file and then later safely to  */
199
        proc_readscsi(inode, file, 0, -1); /* seek in it       */
200
        return(file->f_pos);
201
    default:
202
        return(-EINVAL);
203
    }
204
}
205
 
206
/*
207
 * Overrides for Emacs so that we almost follow Linus's tabbing style.
208
 * Emacs will notice this stuff at the end of the file and automatically
209
 * adjust the settings for this buffer only.  This must remain at the end
210
 * of the file.
211
 * ---------------------------------------------------------------------------
212
 * Local variables:
213
 * c-indent-level: 4
214
 * c-brace-imaginary-offset: 0
215
 * c-brace-offset: -4
216
 * c-argdecl-indent: 4
217
 * c-label-offset: -4
218
 * c-continued-statement-offset: 4
219
 * c-continued-brace-offset: 0
220
 * indent-tabs-mode: nil
221
 * tab-width: 8
222
 * End:
223
 */

powered by: WebSVN 2.1.0

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