Import 2.1.118
[davej-history.git] / drivers / char / ftape / lowlevel / ftape-proc.c
blobee21d92d405ab07f747c374c4ed17c91a0d1dade
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, /* readpage */
116 NULL, /* writepage */
117 NULL, /* bmap */
118 NULL, /* truncate */
119 NULL, /* permission */
123 * Proc filesystem directory entries.
126 static int ftape_get_info(char *page, char **start, off_t off,
127 int count, int dummy)
129 int dummy_eof;
131 return ftape_read_proc(page, start, off, count, &dummy_eof, NULL);
134 static struct proc_dir_entry proc_ftape = {
135 0, /* low_ino */
136 sizeof("ftape")-1, /* namelen */
137 "ftape", /* name */
138 S_IFREG | S_IRUGO, /* mode */
139 1, /* nlink */
140 0, /* uid */
141 0, /* gid */
142 0, /* size */
143 &ftape_proc_inode_operations, /* ops */
144 ftape_get_info, /* get_info */
145 NULL, /* fill_inode */
146 NULL, /* next */
147 NULL, /* parent */
148 NULL, /* subdir */
149 NULL /* data */
152 /* Read ftape proc directory entry.
155 #define PROC_BLOCK_SIZE PAGE_SIZE
157 #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,0)
158 static long ftape_proc_read(struct inode * inode, struct file * file,
159 char * buf, unsigned long nbytes)
160 #else
161 static int ftape_proc_read(struct inode * inode, struct file * file,
162 char * buf, int nbytes)
163 #endif
165 char *page;
166 int retval=0;
167 int eof=0;
168 int n, count;
169 char *start;
170 struct proc_dir_entry * dp;
172 if (nbytes < 0)
173 return -EINVAL;
174 dp = (struct proc_dir_entry *) inode->u.generic_ip;
175 if (!(page = (char*) __get_free_page(GFP_KERNEL)))
176 return -ENOMEM;
178 while ((nbytes > 0) && !eof)
180 count = PROC_BLOCK_SIZE <= nbytes ? PROC_BLOCK_SIZE : nbytes;
182 start = NULL;
183 if (dp->get_info) {
185 * Handle backwards compatibility with the old net
186 * routines.
188 * XXX What gives with the file->f_flags & O_ACCMODE
189 * test? Seems stupid to me....
191 n = dp->get_info(page, &start, file->f_pos, count,
192 (file->f_flags & O_ACCMODE) == O_RDWR);
193 if (n < count)
194 eof = 1;
195 } else
196 break;
198 if (!start) {
200 * For proc files that are less than 4k
202 start = page + file->f_pos;
203 n -= file->f_pos;
204 if (n <= 0)
205 break;
206 if (n > count)
207 n = count;
209 if (n == 0)
210 break; /* End of file */
211 if (n < 0) {
212 if (retval == 0)
213 retval = n;
214 break;
216 #if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
217 copy_to_user(buf, start, n);
218 #else
219 memcpy_tofs(buf, start, n);
220 #endif
221 file->f_pos += n; /* Move down the file */
222 nbytes -= n;
223 buf += n;
224 retval += n;
226 free_page((unsigned long) page);
227 return retval;
230 #else /* LINUX_VERSION_CODE < KERNEL_VER(2,1,28) */
232 #define FT_PROC_REGISTER(parent, child) proc_register(parent, child)
235 * Proc filesystem directory entries.
238 static struct proc_dir_entry proc_ftape = {
239 0, /* low_ino */
240 sizeof("ftape")-1, /* namelen */
241 "ftape", /* name */
242 S_IFREG | S_IRUGO, /* mode */
243 1, /* nlink */
244 0, /* uid */
245 0, /* gid */
246 0, /* size */
247 NULL, /* ops */
248 NULL, /* get_info */
249 NULL, /* fill_inode */
250 NULL, /* next */
251 NULL, /* parent */
252 NULL, /* subdir */
253 NULL, /* data */
254 ftape_read_proc, /* read_proc */
255 NULL /* write_proc */
258 #endif
260 static size_t get_driver_info(char *buf)
262 const char *debug_level[] = { "bugs" ,
263 "errors",
264 "warnings",
265 "informational",
266 "noisy",
267 "program flow",
268 "fdc and dma",
269 "data flow",
270 "anything" };
272 return sprintf(buf,
273 "version : %s\n"
274 "used data rate: %d kbit/sec\n"
275 "dma memory : %d kb\n"
276 "debug messages: %s\n",
277 FTAPE_VERSION,
278 ft_data_rate,
279 FT_BUFF_SIZE * ft_nr_buffers >> 10,
280 debug_level[TRACE_LEVEL]);
283 static size_t get_tapedrive_info(char *buf)
285 return sprintf(buf,
286 "vendor id : 0x%04x\n"
287 "drive name: %s\n"
288 "wind speed: %d ips\n"
289 "wakeup : %s\n"
290 "max. rate : %d kbit/sec\n",
291 ft_drive_type.vendor_id,
292 ft_drive_type.name,
293 ft_drive_type.speed,
294 ((ft_drive_type.wake_up == no_wake_up)
295 ? "No wakeup needed" :
296 ((ft_drive_type.wake_up == wake_up_colorado)
297 ? "Colorado" :
298 ((ft_drive_type.wake_up == wake_up_mountain)
299 ? "Mountain" :
300 ((ft_drive_type.wake_up == wake_up_insight)
301 ? "Motor on" :
302 "Unknown")))),
303 ft_drive_max_rate);
306 static size_t get_cartridge_info(char *buf)
308 if (ftape_init_drive_needed) {
309 return sprintf(buf, "uninitialized\n");
311 if (ft_no_tape) {
312 return sprintf(buf, "no cartridge inserted\n");
314 return sprintf(buf,
315 "segments : %5d\n"
316 "tracks : %5d\n"
317 "length : %5dft\n"
318 "formatted : %3s\n"
319 "writable : %3s\n"
320 "QIC spec. : QIC-%s\n"
321 "fmt-code : %1d\n",
322 ft_segments_per_track,
323 ft_tracks_per_tape,
324 ftape_tape_len,
325 (ft_formatted == 1) ? "yes" : "no",
326 (ft_write_protected == 1) ? "no" : "yes",
327 ((ft_qic_std == QIC_TAPE_QIC40) ? "40" :
328 ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :
329 ((ft_qic_std == QIC_TAPE_QIC3010) ? "3010" :
330 ((ft_qic_std == QIC_TAPE_QIC3020) ? "3020" :
331 "???")))),
332 ft_format_code);
335 static size_t get_controller_info(char *buf)
337 const char *fdc_name[] = { "no fdc",
338 "i8272",
339 "i82077",
340 "i82077AA",
341 "Colorado FC-10 or FC-20",
342 "i82078",
343 "i82078_1" };
345 return sprintf(buf,
346 "FDC type : %s\n"
347 "FDC base : 0x%03x\n"
348 "FDC irq : %d\n"
349 "FDC dma : %d\n"
350 "FDC thr. : %d\n"
351 "max. rate : %d kbit/sec\n",
352 ft_mach2 ? "Mountain MACH-2" : fdc_name[fdc.type],
353 fdc.sra, fdc.irq, fdc.dma,
354 ft_fdc_threshold, ft_fdc_max_rate);
357 static size_t get_history_info(char *buf)
359 size_t len;
361 len = sprintf(buf,
362 "\nFDC isr statistics\n"
363 " id_am_errors : %3d\n"
364 " id_crc_errors : %3d\n"
365 " data_am_errors : %3d\n"
366 " data_crc_errors : %3d\n"
367 " overrun_errors : %3d\n"
368 " no_data_errors : %3d\n"
369 " retries : %3d\n",
370 ft_history.id_am_errors, ft_history.id_crc_errors,
371 ft_history.data_am_errors, ft_history.data_crc_errors,
372 ft_history.overrun_errors, ft_history.no_data_errors,
373 ft_history.retries);
374 len += sprintf(buf + len,
375 "\nECC statistics\n"
376 " crc_errors : %3d\n"
377 " crc_failures : %3d\n"
378 " ecc_failures : %3d\n"
379 " sectors corrected: %3d\n",
380 ft_history.crc_errors, ft_history.crc_failures,
381 ft_history.ecc_failures, ft_history.corrected);
382 len += sprintf(buf + len,
383 "\ntape quality statistics\n"
384 " media defects : %3d\n",
385 ft_history.defects);
386 len += sprintf(buf + len,
387 "\ntape motion statistics\n"
388 " repositions : %3d\n",
389 ft_history.rewinds);
390 return len;
393 int ftape_read_proc(char *page, char **start, off_t off,
394 int count, int *eof, void *data)
396 char *ptr = page;
397 size_t len;
399 ptr += sprintf(ptr, "Kernel Driver\n\n");
400 ptr += get_driver_info(ptr);
401 ptr += sprintf(ptr, "\nTape Drive\n\n");
402 ptr += get_tapedrive_info(ptr);
403 ptr += sprintf(ptr, "\nFDC Controller\n\n");
404 ptr += get_controller_info(ptr);
405 ptr += sprintf(ptr, "\nTape Cartridge\n\n");
406 ptr += get_cartridge_info(ptr);
407 ptr += sprintf(ptr, "\nHistory Record\n\n");
408 ptr += get_history_info(ptr);
410 len = strlen(page);
411 *start = 0;
412 if (off+count >= len) {
413 *eof = 1;
414 } else {
415 *eof = 0;
417 return len;
420 __initfunc(int ftape_proc_init(void))
422 return FT_PROC_REGISTER(&proc_root, &proc_ftape);
425 #ifdef MODULE
426 void ftape_proc_destroy(void)
428 proc_unregister(&proc_root, proc_ftape.low_ino);
430 #endif
432 #endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) */