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