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)
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 $
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 */
40 Please disable CONFIG_FT_PROC_FS in "MCONFIG" or upgrade to a newer kernel!
42 #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,16)
43 #include <linux/init.h>
46 #define __initfunc(__arg) __arg
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
);
67 static int ftape_proc_read(struct inode
* inode
, struct file
* file
,
68 char* buf
, int count
);
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
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
=
90 ftape_proc_read
, /* read */
96 NULL
, /* no special open code */
98 NULL
, /* no special release code */
99 NULL
, /* can't fsync */
102 static struct inode_operations ftape_proc_inode_operations
=
116 NULL
, /* writepage */
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
)
131 return ftape_read_proc(page
, start
, off
, count
, &dummy_eof
, NULL
);
134 static struct proc_dir_entry proc_ftape
= {
136 sizeof("ftape")-1, /* namelen */
138 S_IFREG
| S_IRUGO
, /* mode */
143 &ftape_proc_inode_operations
, /* ops */
144 ftape_get_info
, /* get_info */
145 NULL
, /* fill_inode */
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
)
161 static int ftape_proc_read(struct inode
* inode
, struct file
* file
,
162 char * buf
, int nbytes
)
170 struct proc_dir_entry
* dp
;
174 dp
= (struct proc_dir_entry
*) inode
->u
.generic_ip
;
175 if (!(page
= (char*) __get_free_page(GFP_KERNEL
)))
178 while ((nbytes
> 0) && !eof
)
180 count
= PROC_BLOCK_SIZE
<= nbytes
? PROC_BLOCK_SIZE
: nbytes
;
185 * Handle backwards compatibility with the old net
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
);
200 * For proc files that are less than 4k
202 start
= page
+ file
->f_pos
;
210 break; /* End of file */
216 #if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
217 copy_to_user(buf
, start
, n
);
219 memcpy_tofs(buf
, start
, n
);
221 file
->f_pos
+= n
; /* Move down the file */
226 free_page((unsigned long) page
);
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
= {
240 sizeof("ftape")-1, /* namelen */
242 S_IFREG
| S_IRUGO
, /* mode */
249 NULL
, /* fill_inode */
254 ftape_read_proc
, /* read_proc */
255 NULL
/* write_proc */
260 static size_t get_driver_info(char *buf
)
262 const char *debug_level
[] = { "bugs" ,
274 "used data rate: %d kbit/sec\n"
275 "dma memory : %d kb\n"
276 "debug messages: %s\n",
279 FT_BUFF_SIZE
* ft_nr_buffers
>> 10,
280 debug_level
[TRACE_LEVEL
]);
283 static size_t get_tapedrive_info(char *buf
)
286 "vendor id : 0x%04x\n"
288 "wind speed: %d ips\n"
290 "max. rate : %d kbit/sec\n",
291 ft_drive_type
.vendor_id
,
294 ((ft_drive_type
.wake_up
== no_wake_up
)
295 ? "No wakeup needed" :
296 ((ft_drive_type
.wake_up
== wake_up_colorado
)
298 ((ft_drive_type
.wake_up
== wake_up_mountain
)
300 ((ft_drive_type
.wake_up
== wake_up_insight
)
306 static size_t get_cartridge_info(char *buf
)
308 if (ftape_init_drive_needed
) {
309 return sprintf(buf
, "uninitialized\n");
312 return sprintf(buf
, "no cartridge inserted\n");
320 "QIC spec. : QIC-%s\n"
322 ft_segments_per_track
,
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" :
335 static size_t get_controller_info(char *buf
)
337 const char *fdc_name
[] = { "no fdc",
341 "Colorado FC-10 or FC-20",
347 "FDC base : 0x%03x\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
)
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"
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
,
374 len
+= sprintf(buf
+ len
,
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",
386 len
+= sprintf(buf
+ len
,
387 "\ntape motion statistics\n"
388 " repositions : %3d\n",
393 int ftape_read_proc(char *page
, char **start
, off_t off
,
394 int count
, int *eof
, void *data
)
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
);
412 if (off
+count
>= len
) {
420 __initfunc(int ftape_proc_init(void))
422 return FT_PROC_REGISTER(&proc_root
, &proc_ftape
);
426 void ftape_proc_destroy(void)
428 proc_unregister(&proc_root
, proc_ftape
.low_ino
);
432 #endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) */