Import 2.3.9pre7
[davej-history.git] / drivers / char / ftape / lowlevel / ftape-proc.c
blobef91ff6c985f9e2bcff96773441e4e44eb8ca82b
1 /*
2 * Copyright (C) 1997 Claus-Justus Heine
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-proc.c,v $
20 * $Revision: 1.11 $
21 * $Date: 1997/10/24 14:47:37 $
23 * This file contains the procfs interface for the
24 * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
27 #include <linux/config.h>
29 #if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
31 /* adding proc entries from inside a module is REALLY complicated
32 * for pre-2.1.28 kernels. I don't want to care about it.
35 #include <linux/proc_fs.h>
37 #include <linux/ftape.h>
38 #if LINUX_VERSION_CODE <= KERNEL_VER(1,2,13) /* bail out */
39 #error \
40 Please disable CONFIG_FT_PROC_FS in "MCONFIG" or upgrade to a newer kernel!
41 #endif
42 #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,16)
43 #include <linux/init.h>
44 #else
45 #define __initdata
46 #define __initfunc(__arg) __arg
47 #endif
48 #include <linux/qic117.h>
51 #include "../lowlevel/ftape-io.h"
52 #include "../lowlevel/ftape-ctl.h"
53 #include "../lowlevel/ftape-proc.h"
54 #include "../lowlevel/ftape-tracing.h"
56 static int ftape_read_proc(char *page, char **start, off_t off,
57 int count, int *eof, void *data);
59 #if LINUX_VERSION_CODE < KERNEL_VER(2,1,28)
61 #include <asm/segment.h> /* for memcpy_tofs() */
63 #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,0)
64 static long ftape_proc_read(struct inode* inode, struct file* file,
65 char* buf, unsigned long count);
66 #else
67 static int ftape_proc_read(struct inode* inode, struct file* file,
68 char* buf, int count);
69 #endif
71 #define FT_PROC_REGISTER(parent, child) proc_register_dynamic(parent, child)
74 * Structures for interfacing with the /proc filesystem.
75 * Router creates its own directory /proc/net/router with the folowing
76 * entries:
77 * config device configuration
78 * status global device statistics
79 * <device> entry for each WAN device
83 * Generic /proc/net/ftape/<file> file and inode operations
87 static struct file_operations ftape_proc_fops =
89 NULL, /* lseek */
90 ftape_proc_read, /* read */
91 NULL, /* write */
92 NULL, /* readdir */
93 NULL, /* select */
94 NULL, /* ioctl */
95 NULL, /* mmap */
96 NULL, /* no special open code */
97 NULL, /* flush */
98 NULL, /* no special release code */
99 NULL, /* can't fsync */
102 static struct inode_operations ftape_proc_inode_operations =
104 &ftape_proc_fops,
105 NULL, /* create */
106 NULL, /* lookup */
107 NULL, /* link */
108 NULL, /* unlink */
109 NULL, /* symlink */
110 NULL, /* mkdir */
111 NULL, /* rmdir */
112 NULL, /* mknod */
113 NULL, /* rename */
114 NULL, /* readlink */
115 NULL, /* get_block */
116 NULL, /* readpage */
117 NULL, /* writepage */
118 NULL, /* flushpage */
119 NULL, /* truncate */
120 NULL, /* permission */
121 NULL, /* smap */
122 NULL, /* revalidate */
126 * Proc filesystem directory entries.
129 static int ftape_get_info(char *page, char **start, off_t off,
130 int count, int dummy)
132 int dummy_eof;
134 return ftape_read_proc(page, start, off, count, &dummy_eof, NULL);
137 static struct proc_dir_entry proc_ftape = {
138 0, /* low_ino */
139 sizeof("ftape")-1, /* namelen */
140 "ftape", /* name */
141 S_IFREG | S_IRUGO, /* mode */
142 1, /* nlink */
143 0, /* uid */
144 0, /* gid */
145 0, /* size */
146 &ftape_proc_inode_operations, /* ops */
147 ftape_get_info, /* get_info */
148 NULL, /* fill_inode */
149 NULL, /* next */
150 NULL, /* parent */
151 NULL, /* subdir */
152 NULL /* data */
155 /* Read ftape proc directory entry.
158 #define PROC_BLOCK_SIZE PAGE_SIZE
160 #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,0)
161 static long ftape_proc_read(struct inode * inode, struct file * file,
162 char * buf, unsigned long nbytes)
163 #else
164 static int ftape_proc_read(struct inode * inode, struct file * file,
165 char * buf, int nbytes)
166 #endif
168 char *page;
169 int retval=0;
170 int eof=0;
171 int n, count;
172 char *start;
173 struct proc_dir_entry * dp;
175 if (nbytes < 0)
176 return -EINVAL;
177 dp = (struct proc_dir_entry *) inode->u.generic_ip;
178 if (!(page = (char*) __get_free_page(GFP_KERNEL)))
179 return -ENOMEM;
181 while ((nbytes > 0) && !eof)
183 count = PROC_BLOCK_SIZE <= nbytes ? PROC_BLOCK_SIZE : nbytes;
185 start = NULL;
186 if (dp->get_info) {
188 * Handle backwards compatibility with the old net
189 * routines.
191 * XXX What gives with the file->f_flags & O_ACCMODE
192 * test? Seems stupid to me....
194 n = dp->get_info(page, &start, file->f_pos, count,
195 (file->f_flags & O_ACCMODE) == O_RDWR);
196 if (n < count)
197 eof = 1;
198 } else
199 break;
201 if (!start) {
203 * For proc files that are less than 4k
205 start = page + file->f_pos;
206 n -= file->f_pos;
207 if (n <= 0)
208 break;
209 if (n > count)
210 n = count;
212 if (n == 0)
213 break; /* End of file */
214 if (n < 0) {
215 if (retval == 0)
216 retval = n;
217 break;
219 #if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
220 copy_to_user(buf, start, n);
221 #else
222 memcpy_tofs(buf, start, n);
223 #endif
224 file->f_pos += n; /* Move down the file */
225 nbytes -= n;
226 buf += n;
227 retval += n;
229 free_page((unsigned long) page);
230 return retval;
233 #else /* LINUX_VERSION_CODE < KERNEL_VER(2,1,28) */
235 #define FT_PROC_REGISTER(parent, child) proc_register(parent, child)
238 * Proc filesystem directory entries.
241 static struct proc_dir_entry proc_ftape = {
242 0, /* low_ino */
243 sizeof("ftape")-1, /* namelen */
244 "ftape", /* name */
245 S_IFREG | S_IRUGO, /* mode */
246 1, /* nlink */
247 0, /* uid */
248 0, /* gid */
249 0, /* size */
250 NULL, /* ops */
251 NULL, /* get_info */
252 NULL, /* fill_inode */
253 NULL, /* next */
254 NULL, /* parent */
255 NULL, /* subdir */
256 NULL, /* data */
257 ftape_read_proc, /* read_proc */
258 NULL /* write_proc */
261 #endif
263 static size_t get_driver_info(char *buf)
265 const char *debug_level[] = { "bugs" ,
266 "errors",
267 "warnings",
268 "informational",
269 "noisy",
270 "program flow",
271 "fdc and dma",
272 "data flow",
273 "anything" };
275 return sprintf(buf,
276 "version : %s\n"
277 "used data rate: %d kbit/sec\n"
278 "dma memory : %d kb\n"
279 "debug messages: %s\n",
280 FTAPE_VERSION,
281 ft_data_rate,
282 FT_BUFF_SIZE * ft_nr_buffers >> 10,
283 debug_level[TRACE_LEVEL]);
286 static size_t get_tapedrive_info(char *buf)
288 return sprintf(buf,
289 "vendor id : 0x%04x\n"
290 "drive name: %s\n"
291 "wind speed: %d ips\n"
292 "wakeup : %s\n"
293 "max. rate : %d kbit/sec\n",
294 ft_drive_type.vendor_id,
295 ft_drive_type.name,
296 ft_drive_type.speed,
297 ((ft_drive_type.wake_up == no_wake_up)
298 ? "No wakeup needed" :
299 ((ft_drive_type.wake_up == wake_up_colorado)
300 ? "Colorado" :
301 ((ft_drive_type.wake_up == wake_up_mountain)
302 ? "Mountain" :
303 ((ft_drive_type.wake_up == wake_up_insight)
304 ? "Motor on" :
305 "Unknown")))),
306 ft_drive_max_rate);
309 static size_t get_cartridge_info(char *buf)
311 if (ftape_init_drive_needed) {
312 return sprintf(buf, "uninitialized\n");
314 if (ft_no_tape) {
315 return sprintf(buf, "no cartridge inserted\n");
317 return sprintf(buf,
318 "segments : %5d\n"
319 "tracks : %5d\n"
320 "length : %5dft\n"
321 "formatted : %3s\n"
322 "writable : %3s\n"
323 "QIC spec. : QIC-%s\n"
324 "fmt-code : %1d\n",
325 ft_segments_per_track,
326 ft_tracks_per_tape,
327 ftape_tape_len,
328 (ft_formatted == 1) ? "yes" : "no",
329 (ft_write_protected == 1) ? "no" : "yes",
330 ((ft_qic_std == QIC_TAPE_QIC40) ? "40" :
331 ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :
332 ((ft_qic_std == QIC_TAPE_QIC3010) ? "3010" :
333 ((ft_qic_std == QIC_TAPE_QIC3020) ? "3020" :
334 "???")))),
335 ft_format_code);
338 static size_t get_controller_info(char *buf)
340 const char *fdc_name[] = { "no fdc",
341 "i8272",
342 "i82077",
343 "i82077AA",
344 "Colorado FC-10 or FC-20",
345 "i82078",
346 "i82078_1" };
348 return sprintf(buf,
349 "FDC type : %s\n"
350 "FDC base : 0x%03x\n"
351 "FDC irq : %d\n"
352 "FDC dma : %d\n"
353 "FDC thr. : %d\n"
354 "max. rate : %d kbit/sec\n",
355 ft_mach2 ? "Mountain MACH-2" : fdc_name[fdc.type],
356 fdc.sra, fdc.irq, fdc.dma,
357 ft_fdc_threshold, ft_fdc_max_rate);
360 static size_t get_history_info(char *buf)
362 size_t len;
364 len = sprintf(buf,
365 "\nFDC isr statistics\n"
366 " id_am_errors : %3d\n"
367 " id_crc_errors : %3d\n"
368 " data_am_errors : %3d\n"
369 " data_crc_errors : %3d\n"
370 " overrun_errors : %3d\n"
371 " no_data_errors : %3d\n"
372 " retries : %3d\n",
373 ft_history.id_am_errors, ft_history.id_crc_errors,
374 ft_history.data_am_errors, ft_history.data_crc_errors,
375 ft_history.overrun_errors, ft_history.no_data_errors,
376 ft_history.retries);
377 len += sprintf(buf + len,
378 "\nECC statistics\n"
379 " crc_errors : %3d\n"
380 " crc_failures : %3d\n"
381 " ecc_failures : %3d\n"
382 " sectors corrected: %3d\n",
383 ft_history.crc_errors, ft_history.crc_failures,
384 ft_history.ecc_failures, ft_history.corrected);
385 len += sprintf(buf + len,
386 "\ntape quality statistics\n"
387 " media defects : %3d\n",
388 ft_history.defects);
389 len += sprintf(buf + len,
390 "\ntape motion statistics\n"
391 " repositions : %3d\n",
392 ft_history.rewinds);
393 return len;
396 int ftape_read_proc(char *page, char **start, off_t off,
397 int count, int *eof, void *data)
399 char *ptr = page;
400 size_t len;
402 ptr += sprintf(ptr, "Kernel Driver\n\n");
403 ptr += get_driver_info(ptr);
404 ptr += sprintf(ptr, "\nTape Drive\n\n");
405 ptr += get_tapedrive_info(ptr);
406 ptr += sprintf(ptr, "\nFDC Controller\n\n");
407 ptr += get_controller_info(ptr);
408 ptr += sprintf(ptr, "\nTape Cartridge\n\n");
409 ptr += get_cartridge_info(ptr);
410 ptr += sprintf(ptr, "\nHistory Record\n\n");
411 ptr += get_history_info(ptr);
413 len = strlen(page);
414 *start = 0;
415 if (off+count >= len) {
416 *eof = 1;
417 } else {
418 *eof = 0;
420 return len;
423 __initfunc(int ftape_proc_init(void))
425 return FT_PROC_REGISTER(&proc_root, &proc_ftape);
428 #ifdef MODULE
429 void ftape_proc_destroy(void)
431 proc_unregister(&proc_root, proc_ftape.low_ino);
433 #endif
435 #endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) */