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