This source file includes following definitions.
- count_dir_entries
- proc_lookupscsi
- proc_readscsidir
- get_not_present_info
- proc_readscsi
- proc_writescsi
- proc_scsilseek
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include <linux/autoconf.h>
24 #include <asm/segment.h>
25 #include <linux/errno.h>
26 #include <linux/sched.h>
27 #include <linux/proc_fs.h>
28 #include <linux/stat.h>
29 #include <linux/config.h>
30 #include <linux/mm.h>
31
32
33 static int proc_readscsi(struct inode * inode, struct file * file,
34 char * buf, int count);
35 static int proc_writescsi(struct inode * inode, struct file * file,
36 const char * buf, int count);
37 static int proc_readscsidir(struct inode *, struct file *,
38 void *, filldir_t filldir);
39 static int proc_lookupscsi(struct inode *,const char *,int,struct inode **);
40 static int proc_scsilseek(struct inode *, struct file *, off_t, int);
41
42 extern uint count_templates(void);
43 extern void build_proc_dir_hba_entries(uint);
44
45
46 extern int (* dispatch_scsi_info_ptr)(int, char *, char **, off_t, int, int);
47
48
49 static struct file_operations proc_scsi_operations = {
50 proc_scsilseek,
51 proc_readscsi,
52 proc_writescsi,
53 proc_readscsidir,
54 NULL,
55 NULL,
56 NULL,
57 NULL,
58 NULL,
59 NULL
60 };
61
62
63
64
65 struct inode_operations proc_scsi_inode_operations = {
66 &proc_scsi_operations,
67 NULL,
68 proc_lookupscsi,
69 NULL,
70 NULL,
71 NULL,
72 NULL,
73 NULL,
74 NULL,
75 NULL,
76 NULL,
77 NULL,
78 NULL,
79 NULL,
80 NULL
81 };
82
83 struct proc_dir_entry proc_scsi = {
84 PROC_SCSI, 4, "scsi",
85 S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
86 0, &proc_scsi_inode_operations,
87 NULL, NULL,
88 NULL,
89 &proc_root, NULL
90 };
91
92 struct proc_dir_entry scsi_dir[PROC_SCSI_FILE - PROC_SCSI_SCSI + 3];
93 struct proc_dir_entry scsi_hba_dir[(PROC_SCSI_LAST - PROC_SCSI_FILE) * 4];
94
95 static struct proc_dir_entry scsi_dir2[] = {
96 { PROC_SCSI, 1, "." },
97 { PROC_ROOT_INO, 2, ".." },
98 { PROC_SCSI_NOT_PRESENT, 11, "not.present" },
99 { 0, 0, NULL }
100 };
101
102 inline static uint count_dir_entries(uint inode, uint *num)
103 {
104 struct proc_dir_entry *dir;
105 uint index, flag;
106
107 (uint) *num = flag = index = 0;
108
109 if(dispatch_scsi_info_ptr) {
110 if (inode == PROC_SCSI) {
111 dir = scsi_dir;
112 while(dir[(uint)*num].low_ino)
113 (*num)++;
114 } else {
115
116
117
118
119
120 dir = scsi_hba_dir;
121 while(dir[index].low_ino || dir[index].low_ino <= PROC_SCSI_LAST) {
122 if(dir[index].low_ino == inode)
123 flag = 1;
124 if(dir[index].low_ino == 0) {
125 if(flag == 1)
126 break;
127 else
128 *num = 0;
129 } else {
130 (*num)++;
131 }
132 index++;
133 }
134 return(index - (*num));
135 }
136 }
137 else {
138 dir = scsi_dir2;
139 while(dir[(uint)*num].low_ino)
140 (*num)++;
141 }
142 return(0);
143 }
144
145 static int proc_lookupscsi(struct inode * dir, const char * name, int len,
146 struct inode ** result)
147 {
148 struct proc_dir_entry *de = NULL;
149
150 *result = NULL;
151 if (!dir)
152 return(-ENOENT);
153 if (!S_ISDIR(dir->i_mode)) {
154 iput(dir);
155 return(-ENOENT);
156 }
157 if (dispatch_scsi_info_ptr != NULL) {
158 if (dir->i_ino <= PROC_SCSI_SCSI)
159 de = scsi_dir;
160 else {
161 de = &scsi_hba_dir[dispatch_scsi_info_ptr(dir->i_ino, 0, 0, 0, 0, 2)];
162 }
163 }
164 else
165 de = scsi_dir2;
166
167 for (; de->name ; de++) {
168 if (!proc_match(len, name, de))
169 continue;
170 *result = proc_get_inode(dir->i_sb, de->low_ino, de);
171 iput(dir);
172 if (!*result)
173 return(-ENOENT);
174 return(0);
175 }
176 iput(dir);
177 return(-ENOENT);
178 }
179
180 static int proc_readscsidir(struct inode * inode, struct file * filp,
181 void * dirent, filldir_t filldir)
182 {
183 struct proc_dir_entry * de;
184 uint index, num;
185
186 num = 0;
187
188 if (!inode || !S_ISDIR(inode->i_mode))
189 return(-EBADF);
190
191 index = count_dir_entries(inode->i_ino, &num);
192
193 while (((unsigned) filp->f_pos + index) < index + num) {
194 if (dispatch_scsi_info_ptr) {
195 if (inode->i_ino <= PROC_SCSI_SCSI)
196 de = scsi_dir + filp->f_pos;
197 else
198 de = scsi_hba_dir + filp->f_pos + index;
199 }
200 else {
201 de = scsi_dir2 + filp->f_pos;
202 }
203 if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino)<0)
204 break;
205 filp->f_pos++;
206 }
207 return(0);
208 }
209
210 int get_not_present_info(char *buffer, char **start, off_t offset, int length)
211 {
212 int len, pos, begin;
213
214 begin = 0;
215 pos = len = sprintf(buffer,
216 "No low-level scsi modules are currently present\n");
217 if(pos < offset) {
218 len = 0;
219 begin = pos;
220 }
221
222 *start = buffer + (offset - begin);
223 len -= (offset - begin);
224 if(len > length)
225 len = length;
226
227 return(len);
228 }
229
230 #define PROC_BLOCK_SIZE (3*1024)
231
232
233
234 static int proc_readscsi(struct inode * inode, struct file * file,
235 char * buf, int count)
236 {
237 int length;
238 int bytes = count;
239 int copied = 0;
240 int thistime;
241 char * page;
242 char * start;
243
244 if (count < -1)
245 return(-EINVAL);
246
247
248 if (!(page = (char *) __get_free_page(GFP_KERNEL)))
249 return(-ENOMEM);
250
251 while(bytes > 0 || count == -1) {
252 thistime = bytes;
253 if(bytes > PROC_BLOCK_SIZE || count == -1)
254 thistime = PROC_BLOCK_SIZE;
255
256 if(dispatch_scsi_info_ptr)
257 length = dispatch_scsi_info_ptr(inode->i_ino, page, &start,
258 file->f_pos, thistime, 0);
259 else
260 length = get_not_present_info(page, &start, file->f_pos, thistime);
261 if(length < 0) {
262 free_page((ulong) page);
263 return(length);
264 }
265
266
267
268
269
270
271 if (length <= 0)
272 break;
273
274
275
276
277 if (count != -1)
278 memcpy_tofs(buf + copied, start, length);
279 file->f_pos += length;
280 bytes -= length;
281 copied += length;
282
283 if(length < thistime)
284 break;
285
286 }
287
288 free_page((ulong) page);
289 return(copied);
290 }
291
292
293 static int proc_writescsi(struct inode * inode, struct file * file,
294 const char * buf, int count)
295 {
296 int ret = 0;
297 char * page;
298
299 if (!(page = (char *) __get_free_page(GFP_KERNEL)))
300 return(-ENOMEM);
301
302 if(count > PROC_BLOCK_SIZE) {
303 return(-EOVERFLOW);
304 }
305
306 if(dispatch_scsi_info_ptr != NULL) {
307 memcpy_fromfs(page, buf, count);
308 ret = dispatch_scsi_info_ptr(inode->i_ino, page, 0, 0, count, 1);
309 } else {
310 free_page((ulong) page);
311 return(-ENOPKG);
312 }
313
314 free_page((ulong) page);
315 return(ret);
316 }
317
318
319 static int proc_scsilseek(struct inode * inode, struct file * file,
320 off_t offset, int orig)
321 {
322 switch (orig) {
323 case 0:
324 file->f_pos = offset;
325 return(file->f_pos);
326 case 1:
327 file->f_pos += offset;
328 return(file->f_pos);
329 case 2:
330 if (offset)
331 return(-EINVAL);
332 proc_readscsi(inode, file, 0, -1);
333 return(file->f_pos);
334 default:
335 return(-EINVAL);
336 }
337 }
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356