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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [scsi_proc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/drivers/scsi/scsi_proc.c
3
 *
4
 * The functions in this file provide an interface between
5
 * the PROC file system and the SCSI device drivers
6
 * It is mainly used for debugging, statistics and to pass
7
 * information directly to the lowlevel driver.
8
 *
9
 * (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de
10
 * Version: 0.99.8   last change: 95/09/13
11
 *
12
 * generic command parser provided by:
13
 * Andreas Heilwagen <crashcar@informatik.uni-koblenz.de>
14
 *
15
 * generic_proc_info() support of xxxx_info() by:
16
 * Michael A. Griffith <grif@acm.org>
17
 */
18
 
19
#include <linux/config.h>       /* for CONFIG_PROC_FS */
20
#define __NO_VERSION__
21
#include <linux/module.h>
22
 
23
#include <linux/string.h>
24
#include <linux/mm.h>
25
#include <linux/slab.h>
26
#include <linux/proc_fs.h>
27
#include <linux/errno.h>
28
#include <linux/stat.h>
29
#include <linux/blk.h>
30
 
31
#include <asm/uaccess.h>
32
 
33
#include "scsi.h"
34
#include "hosts.h"
35
 
36
#ifndef TRUE
37
#define TRUE  1
38
#define FALSE 0
39
#endif
40
 
41
#ifdef CONFIG_PROC_FS
42
 
43
/* generic_proc_info
44
 * Used if the driver currently has no own support for /proc/scsi
45
 */
46
int generic_proc_info(char *buffer, char **start, off_t offset, int length,
47
                      const char *(*info) (struct Scsi_Host *),
48
                      struct Scsi_Host *sh)
49
{
50
        int len, pos, begin;
51
 
52
        begin = 0;
53
        if (info && sh) {
54
                pos = len = sprintf(buffer, "%s\n", info(sh));
55
        } else {
56
                pos = len = sprintf(buffer,
57
                        "The driver does not yet support the proc-fs\n");
58
        }
59
        if (pos < offset) {
60
                len = 0;
61
                begin = pos;
62
        }
63
        *start = buffer + (offset - begin);     /* Start of wanted data */
64
        len -= (offset - begin);
65
        if (len > length)
66
                len = length;
67
 
68
        return (len);
69
}
70
 
71
/* dispatch_scsi_info is the central dispatcher
72
 * It is the interface between the proc-fs and the SCSI subsystem code
73
 */
74
static int proc_scsi_read(char *buffer, char **start, off_t offset,
75
        int length, int *eof, void *data)
76
{
77
        struct Scsi_Host *hpnt = data;
78
        int n;
79
 
80
        if (hpnt->hostt->proc_info == NULL)
81
                n = generic_proc_info(buffer, start, offset, length,
82
                                      hpnt->hostt->info, hpnt);
83
        else
84
                n = (hpnt->hostt->proc_info(buffer, start, offset,
85
                                           length, hpnt->host_no, 0));
86
        *eof = (n<length);
87
        return n;
88
}
89
 
90
#define PROC_BLOCK_SIZE (3*1024)     /* 4K page size, but our output routines 
91
                                      * use some slack for overruns
92
                                      */
93
 
94
static int proc_scsi_write(struct file * file, const char * buf,
95
                           unsigned long count, void *data)
96
{
97
        struct Scsi_Host *hpnt = data;
98
        ssize_t ret = 0;
99
        char * page;
100
        char *start;
101
 
102
        if (hpnt->hostt->proc_info == NULL)
103
                ret = -ENOSYS;
104
 
105
        if (count > PROC_BLOCK_SIZE)
106
                return -EOVERFLOW;
107
 
108
        if (!(page = (char *) __get_free_page(GFP_KERNEL)))
109
                return -ENOMEM;
110
        if(copy_from_user(page, buf, count))
111
        {
112
                free_page((ulong) page);
113
                return -EFAULT;
114
        }
115
 
116
        ret = hpnt->hostt->proc_info(page, &start, 0, count,
117
                                     hpnt->host_no, 1);
118
 
119
        free_page((ulong) page);
120
        return(ret);
121
}
122
 
123
void build_proc_dir_entries(Scsi_Host_Template * tpnt)
124
{
125
        struct Scsi_Host *hpnt;
126
        char name[10];  /* see scsi_unregister_host() */
127
 
128
        tpnt->proc_dir = proc_mkdir(tpnt->proc_name, proc_scsi);
129
        if (!tpnt->proc_dir) {
130
                printk(KERN_ERR "Unable to proc_mkdir in scsi.c/build_proc_dir_entries");
131
                return;
132
        }
133
        tpnt->proc_dir->owner = tpnt->module;
134
 
135
        hpnt = scsi_hostlist;
136
        while (hpnt) {
137
                if (tpnt == hpnt->hostt) {
138
                        struct proc_dir_entry *p;
139
                        sprintf(name,"%d",hpnt->host_no);
140
                        p = create_proc_read_entry(name,
141
                                        S_IFREG | S_IRUGO | S_IWUSR,
142
                                        tpnt->proc_dir,
143
                                        proc_scsi_read,
144
                                        (void *)hpnt);
145
                        if (!p)
146
                                panic("Not enough memory to register SCSI HBA in /proc/scsi !\n");
147
                        p->write_proc=proc_scsi_write;
148
                        p->owner = tpnt->module;
149
                }
150
                hpnt = hpnt->next;
151
        }
152
}
153
 
154
/*
155
 *  parseHandle *parseInit(char *buf, char *cmdList, int cmdNum);
156
 *              gets a pointer to a null terminated data buffer
157
 *              and a list of commands with blanks as delimiter
158
 *      in between.
159
 *      The commands have to be alphanumerically sorted.
160
 *      cmdNum has to contain the number of commands.
161
 *              On success, a pointer to a handle structure
162
 *              is returned, NULL on failure
163
 *
164
 *      int parseOpt(parseHandle *handle, char **param);
165
 *              processes the next parameter. On success, the
166
 *              index of the appropriate command in the cmdList
167
 *              is returned, starting with zero.
168
 *              param points to the null terminated parameter string.
169
 *              On failure, -1 is returned.
170
 *
171
 *      The databuffer buf may only contain pairs of commands
172
 *          options, separated by blanks:
173
 *              <Command> <Parameter> [<Command> <Parameter>]*
174
 */
175
 
176
typedef struct {
177
        char *buf,              /* command buffer  */
178
        *cmdList,               /* command list    */
179
        *bufPos,                /* actual position */
180
        **cmdPos,               /* cmdList index   */
181
         cmdNum;                /* cmd number      */
182
} parseHandle;
183
 
184
inline int parseFree(parseHandle * handle)
185
{                               /* free memory     */
186
        kfree(handle->cmdPos);
187
        kfree(handle);
188
 
189
        return -1;
190
}
191
 
192
parseHandle *parseInit(char *buf, char *cmdList, int cmdNum)
193
{
194
        char *ptr;              /* temp pointer    */
195
        parseHandle *handle;    /* new handle      */
196
 
197
        if (!buf || !cmdList)   /* bad input ?     */
198
                return NULL;
199
        handle = (parseHandle *) kmalloc(sizeof(parseHandle), GFP_KERNEL);
200
        if (!handle)
201
                return NULL;    /* out of memory   */
202
        handle->cmdPos = (char **) kmalloc(sizeof(int) * cmdNum, GFP_KERNEL);
203
        if (!handle->cmdPos) {
204
                kfree(handle);
205
                return NULL;    /* out of memory   */
206
        }
207
        handle->buf = handle->bufPos = buf;     /* init handle     */
208
        handle->cmdList = cmdList;
209
        handle->cmdNum = cmdNum;
210
 
211
        handle->cmdPos[cmdNum = 0] = cmdList;
212
        for (ptr = cmdList; *ptr; ptr++) {      /* scan command string */
213
                if (*ptr == ' ') {      /* and insert zeroes   */
214
                        *ptr++ = 0;
215
                        handle->cmdPos[++cmdNum] = ptr++;
216
                }
217
        }
218
        return handle;
219
}
220
 
221
int parseOpt(parseHandle * handle, char **param)
222
{
223
        int cmdIndex = 0, cmdLen = 0;
224
        char *startPos;
225
 
226
        if (!handle)            /* invalid handle  */
227
                return (parseFree(handle));
228
        /* skip spaces     */
229
        for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++);
230
        if (!*(handle->bufPos))
231
                return (parseFree(handle));     /* end of data     */
232
 
233
        startPos = handle->bufPos;      /* store cmd start */
234
        for (; handle->cmdPos[cmdIndex][cmdLen] && *(handle->bufPos); handle->bufPos++) {       /* no string end?  */
235
                for (;;) {
236
                        if (*(handle->bufPos) == handle->cmdPos[cmdIndex][cmdLen])
237
                                break;  /* char matches ?  */
238
                        else if (memcmp(startPos, (char *) (handle->cmdPos[++cmdIndex]), cmdLen))
239
                                return (parseFree(handle));     /* unknown command */
240
 
241
                        if (cmdIndex >= handle->cmdNum)
242
                                return (parseFree(handle));     /* unknown command */
243
                }
244
 
245
                cmdLen++;       /* next char       */
246
        }
247
 
248
        /* Get param. First skip all blanks, then insert zero after param  */
249
 
250
        for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++);
251
        *param = handle->bufPos;
252
 
253
        for (; *(handle->bufPos) && *(handle->bufPos) != ' '; handle->bufPos++);
254
        *(handle->bufPos++) = 0;
255
 
256
        return (cmdIndex);
257
}
258
 
259
void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len)
260
{
261
 
262
        int x, y = *size;
263
        extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
264
 
265
        y = sprintf(buffer + len,
266
             "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",
267
                    scd->host->host_no, scd->channel, scd->id, scd->lun);
268
        for (x = 0; x < 8; x++) {
269
                if (scd->vendor[x] >= 0x20)
270
                        y += sprintf(buffer + len + y, "%c", scd->vendor[x]);
271
                else
272
                        y += sprintf(buffer + len + y, " ");
273
        }
274
        y += sprintf(buffer + len + y, " Model: ");
275
        for (x = 0; x < 16; x++) {
276
                if (scd->model[x] >= 0x20)
277
                        y += sprintf(buffer + len + y, "%c", scd->model[x]);
278
                else
279
                        y += sprintf(buffer + len + y, " ");
280
        }
281
        y += sprintf(buffer + len + y, " Rev: ");
282
        for (x = 0; x < 4; x++) {
283
                if (scd->rev[x] >= 0x20)
284
                        y += sprintf(buffer + len + y, "%c", scd->rev[x]);
285
                else
286
                        y += sprintf(buffer + len + y, " ");
287
        }
288
        y += sprintf(buffer + len + y, "\n");
289
 
290
        y += sprintf(buffer + len + y, "  Type:   %s ",
291
                     scd->type < MAX_SCSI_DEVICE_CODE ?
292
               scsi_device_types[(int) scd->type] : "Unknown          ");
293
        y += sprintf(buffer + len + y, "               ANSI"
294
                     " SCSI revision: %02x", (scd->scsi_level - 1) ? scd->scsi_level - 1 : 1);
295
        if (scd->scsi_level == 2)
296
                y += sprintf(buffer + len + y, " CCS\n");
297
        else
298
                y += sprintf(buffer + len + y, "\n");
299
 
300
        *size = y;
301
        return;
302
}
303
 
304
#else                           /* if !CONFIG_PROC_FS */
305
 
306
void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len)
307
{
308
}
309
 
310
#endif                          /* CONFIG_PROC_FS */

powered by: WebSVN 2.1.0

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