3 * (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de
5 * The original version was derived from linux/fs/proc/net.c,
6 * which is Copyright (C) 1991, 1992 Linus Torvalds.
7 * Much has been rewritten, but some of the code still remains.
9 * /proc/scsi directory handling functions
11 * last change: 95/07/04
13 * Initial version: March '95
14 * 95/05/15 Added subdirectories for each driver and show every
15 * registered HBA as a single file.
16 * 95/05/30 Added rudimentary write support for parameter passing
17 * 95/07/04 Fixed bugs in directory handling
18 * 95/09/13 Update to support the new proc-dir tree
20 * TODO: Improve support to write to the driver files
21 * Add some more comments
23 #include <linux/errno.h>
24 #include <linux/sched.h>
25 #include <linux/proc_fs.h>
26 #include <linux/stat.h>
29 #include <asm/uaccess.h>
31 /* forward references */
32 static ssize_t
proc_readscsi(struct file
* file
, char * buf
,
33 size_t count
, loff_t
*ppos
);
34 static ssize_t
proc_writescsi(struct file
* file
, const char * buf
,
35 size_t count
, loff_t
*ppos
);
36 static long long proc_scsilseek(struct file
*, long long, int);
38 extern void build_proc_dir_hba_entries(uint
);
40 /* the *_get_info() functions are in the respective scsi driver code */
41 int (* dispatch_scsi_info_ptr
) (int ino
, char *buffer
, char **start
,
42 off_t offset
, int length
, int inout
) = 0;
44 static struct file_operations proc_scsi_operations
= {
45 proc_scsilseek
, /* lseek */
46 proc_readscsi
, /* read */
47 proc_writescsi
, /* write */
48 proc_readdir
, /* readdir */
52 NULL
, /* no special open code */
54 NULL
, /* no special release code */
55 NULL
/* can't fsync */
59 * proc directories can do almost nothing..
61 struct inode_operations proc_scsi_inode_operations
= {
62 &proc_scsi_operations
, /* default scsi directory file-ops */
64 proc_lookup
, /* lookup */
73 NULL
, /* follow_link */
79 NULL
, /* permission */
84 int get_not_present_info(char *buffer
, char **start
, off_t offset
, int length
)
89 pos
= len
= sprintf(buffer
,
90 "No low-level scsi modules are currently present\n");
96 *start
= buffer
+ (offset
- begin
); /* Start of wanted data */
97 len
-= (offset
- begin
);
104 #define PROC_BLOCK_SIZE (3*1024) /* 4K page size, but our output routines
105 * use some slack for overruns
108 static ssize_t
proc_readscsi(struct file
* file
, char * buf
,
109 size_t count
, loff_t
*ppos
)
111 struct inode
* inode
= file
->f_dentry
->d_inode
;
113 ssize_t bytes
= count
;
119 if (!(page
= (char *) __get_free_page(GFP_KERNEL
)))
124 if(bytes
> PROC_BLOCK_SIZE
)
125 thistime
= PROC_BLOCK_SIZE
;
127 if(dispatch_scsi_info_ptr
)
128 length
= dispatch_scsi_info_ptr(inode
->i_ino
, page
, &start
,
131 length
= get_not_present_info(page
, &start
, *ppos
, thistime
);
133 free_page((ulong
) page
);
138 * We have been given a non page aligned block of
139 * the data we asked for + a bit. We have been given
140 * the start pointer and we know the length..
147 copy_to_user(buf
+ copied
, start
, length
);
148 *ppos
+= length
; /* Move down the file */
152 if(length
< thistime
)
153 break; /* End of file */
157 free_page((ulong
) page
);
162 static ssize_t
proc_writescsi(struct file
* file
, const char * buf
,
163 size_t count
, loff_t
*ppos
)
165 struct inode
* inode
= file
->f_dentry
->d_inode
;
169 if(count
> PROC_BLOCK_SIZE
) {
173 if(dispatch_scsi_info_ptr
!= NULL
) {
174 if (!(page
= (char *) __get_free_page(GFP_KERNEL
)))
176 copy_from_user(page
, buf
, count
);
177 ret
= dispatch_scsi_info_ptr(inode
->i_ino
, page
, 0, 0, count
, 1);
179 return(-ENOPKG
); /* Nothing here */
181 free_page((ulong
) page
);
186 static long long proc_scsilseek(struct file
* file
, long long offset
, int orig
)
190 file
->f_pos
= offset
;
193 file
->f_pos
+= offset
;
203 * Overrides for Emacs so that we almost follow Linus's tabbing style.
204 * Emacs will notice this stuff at the end of the file and automatically
205 * adjust the settings for this buffer only. This must remain at the end
207 * ---------------------------------------------------------------------------
210 * c-brace-imaginary-offset: 0
212 * c-argdecl-indent: 4
214 * c-continued-statement-offset: 4
215 * c-continued-brace-offset: 0
216 * indent-tabs-mode: nil