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