1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/config.h>
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
44
45
46int 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);
64 len -= (offset - begin);
65 if (len > length)
66 len = length;
67
68 return (len);
69}
70
71
72
73
74static 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)
91
92
93
94static 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
123void build_proc_dir_entries(Scsi_Host_Template * tpnt)
124{
125 struct Scsi_Host *hpnt;
126 char name[10];
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176typedef struct {
177 char *buf,
178 *cmdList,
179 *bufPos,
180 **cmdPos,
181 cmdNum;
182} parseHandle;
183
184inline int parseFree(parseHandle * handle)
185{
186 kfree(handle->cmdPos);
187 kfree(handle);
188
189 return -1;
190}
191
192parseHandle *parseInit(char *buf, char *cmdList, int cmdNum)
193{
194 char *ptr;
195 parseHandle *handle;
196
197 if (!buf || !cmdList)
198 return NULL;
199 handle = (parseHandle *) kmalloc(sizeof(parseHandle), GFP_KERNEL);
200 if (!handle)
201 return NULL;
202 handle->cmdPos = (char **) kmalloc(sizeof(int) * cmdNum, GFP_KERNEL);
203 if (!handle->cmdPos) {
204 kfree(handle);
205 return NULL;
206 }
207 handle->buf = handle->bufPos = buf;
208 handle->cmdList = cmdList;
209 handle->cmdNum = cmdNum;
210
211 handle->cmdPos[cmdNum = 0] = cmdList;
212 for (ptr = cmdList; *ptr; ptr++) {
213 if (*ptr == ' ') {
214 *ptr++ = 0;
215 handle->cmdPos[++cmdNum] = ptr++;
216 }
217 }
218 return handle;
219}
220
221int parseOpt(parseHandle * handle, char **param)
222{
223 int cmdIndex = 0, cmdLen = 0;
224 char *startPos;
225
226 if (!handle)
227 return (parseFree(handle));
228
229 for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++);
230 if (!*(handle->bufPos))
231 return (parseFree(handle));
232
233 startPos = handle->bufPos;
234 for (; handle->cmdPos[cmdIndex][cmdLen] && *(handle->bufPos); handle->bufPos++) {
235 for (;;) {
236 if (*(handle->bufPos) == handle->cmdPos[cmdIndex][cmdLen])
237 break;
238 else if (memcmp(startPos, (char *) (handle->cmdPos[++cmdIndex]), cmdLen))
239 return (parseFree(handle));
240
241 if (cmdIndex >= handle->cmdNum)
242 return (parseFree(handle));
243 }
244
245 cmdLen++;
246 }
247
248
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
259void 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
305
306void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len)
307{
308}
309
310#endif
311