[PATCH] devfs: Remove the devfs_fs_kernel.h file from the tree
[safe/jmp/linux-2.6] / drivers / char / ftape / zftape / zftape-init.c
1 /*
2  *      Copyright (C) 1996, 1997 Claus-Justus Heine.
3
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.
8
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.
13
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.
17
18  *
19  *      This file contains the code that registers the zftape frontend 
20  *      to the ftape floppy tape driver for Linux
21  */
22
23 #include <linux/config.h>
24 #include <linux/module.h>
25 #include <linux/errno.h>
26 #include <linux/fs.h>
27 #include <linux/kernel.h>
28 #include <linux/signal.h>
29 #include <linux/major.h>
30 #include <linux/slab.h>
31 #ifdef CONFIG_KMOD
32 #include <linux/kmod.h>
33 #endif
34 #include <linux/fcntl.h>
35 #include <linux/smp_lock.h>
36
37 #include <linux/zftape.h>
38 #include <linux/init.h>
39 #include <linux/device.h>
40
41 #include "../zftape/zftape-init.h"
42 #include "../zftape/zftape-read.h"
43 #include "../zftape/zftape-write.h"
44 #include "../zftape/zftape-ctl.h"
45 #include "../zftape/zftape-buffers.h"
46
47 MODULE_AUTHOR("(c) 1996, 1997 Claus-Justus Heine "
48               "(claus@momo.math.rwth-aachen.de)");
49 MODULE_DESCRIPTION(ZFTAPE_VERSION " - "
50                    "VFS interface for the Linux floppy tape driver. "
51                    "Support for QIC-113 compatible volume table "
52                    "and builtin compression (lzrw3 algorithm)");
53 MODULE_SUPPORTED_DEVICE("char-major-27");
54 MODULE_LICENSE("GPL");
55
56 /*      Global vars.
57  */
58 struct zft_cmpr_ops *zft_cmpr_ops = NULL;
59 const ftape_info *zft_status;
60
61 /*      Local vars.
62  */
63 static unsigned long busy_flag;
64
65 static sigset_t orig_sigmask;
66
67 /*  the interface to the kernel vfs layer
68  */
69
70 /* Note about llseek():
71  *
72  * st.c and tpqic.c update fp->f_pos but don't implment llseek() and
73  * initialize the llseek component of the file_ops struct with NULL.
74  * This means that the user will get the default seek, but the tape
75  * device will not respect the new position, but happily read from the
76  * old position. Think a zftape specific llseek() function would be
77  * better, returning -ESPIPE. TODO.
78  */
79
80 static int  zft_open (struct inode *ino, struct file *filep);
81 static int zft_close(struct inode *ino, struct file *filep);
82 static int  zft_ioctl(struct inode *ino, struct file *filep,
83                       unsigned int command, unsigned long arg);
84 static int  zft_mmap(struct file *filep, struct vm_area_struct *vma);
85 static ssize_t zft_read (struct file *fp, char __user *buff,
86                          size_t req_len, loff_t *ppos);
87 static ssize_t zft_write(struct file *fp, const char __user *buff,
88                          size_t req_len, loff_t *ppos);
89
90 static struct file_operations zft_cdev =
91 {
92         .owner          = THIS_MODULE,
93         .read           = zft_read,
94         .write          = zft_write,
95         .ioctl          = zft_ioctl,
96         .mmap           = zft_mmap,
97         .open           = zft_open,
98         .release        = zft_close,
99 };
100
101 static struct class *zft_class;
102
103 /*      Open floppy tape device
104  */
105 static int zft_open(struct inode *ino, struct file *filep)
106 {
107         int result;
108         TRACE_FUN(ft_t_flow);
109
110         nonseekable_open(ino, filep);
111         TRACE(ft_t_flow, "called for minor %d", iminor(ino));
112         if ( test_and_set_bit(0,&busy_flag) ) {
113                 TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy");
114         }
115         if ((iminor(ino) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND))
116              > 
117             FTAPE_SEL_D) {
118                 clear_bit(0,&busy_flag);
119                 TRACE_ABORT(-ENXIO, ft_t_err, "failed: invalid unit nr");
120         }
121         orig_sigmask = current->blocked;
122         sigfillset(&current->blocked);
123         result = _zft_open(iminor(ino), filep->f_flags & O_ACCMODE);
124         if (result < 0) {
125                 current->blocked = orig_sigmask; /* restore mask */
126                 clear_bit(0,&busy_flag);
127                 TRACE_ABORT(result, ft_t_err, "_ftape_open failed");
128         } else {
129                 /* Mask signals that will disturb proper operation of the
130                  * program that is calling.
131                  */
132                 current->blocked = orig_sigmask;
133                 sigaddsetmask (&current->blocked, _DO_BLOCK);
134                 TRACE_EXIT 0;
135         }
136 }
137
138 /*      Close floppy tape device
139  */
140 static int zft_close(struct inode *ino, struct file *filep)
141 {
142         int result;
143         TRACE_FUN(ft_t_flow);
144
145         if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit) {
146                 TRACE(ft_t_err, "failed: not busy or wrong unit");
147                 TRACE_EXIT 0;
148         }
149         sigfillset(&current->blocked);
150         result = _zft_close();
151         if (result < 0) {
152                 TRACE(ft_t_err, "_zft_close failed");
153         }
154         current->blocked = orig_sigmask; /* restore before open state */
155         clear_bit(0,&busy_flag);
156         TRACE_EXIT 0;
157 }
158
159 /*      Ioctl for floppy tape device
160  */
161 static int zft_ioctl(struct inode *ino, struct file *filep,
162                      unsigned int command, unsigned long arg)
163 {
164         int result = -EIO;
165         sigset_t old_sigmask;
166         TRACE_FUN(ft_t_flow);
167
168         if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
169                 TRACE_ABORT(-EIO, ft_t_err,
170                             "failed: not busy, failure or wrong unit");
171         }
172         old_sigmask = current->blocked; /* save mask */
173         sigfillset(&current->blocked);
174         /* This will work as long as sizeof(void *) == sizeof(long) */
175         result = _zft_ioctl(command, (void __user *) arg);
176         current->blocked = old_sigmask; /* restore mask */
177         TRACE_EXIT result;
178 }
179
180 /*      Ioctl for floppy tape device
181  */
182 static int  zft_mmap(struct file *filep, struct vm_area_struct *vma)
183 {
184         int result = -EIO;
185         sigset_t old_sigmask;
186         TRACE_FUN(ft_t_flow);
187
188         if ( !test_bit(0,&busy_flag) || 
189             iminor(filep->f_dentry->d_inode) != zft_unit || 
190             ft_failure)
191         {
192                 TRACE_ABORT(-EIO, ft_t_err,
193                             "failed: not busy, failure or wrong unit");
194         }
195         old_sigmask = current->blocked; /* save mask */
196         sigfillset(&current->blocked);
197         if ((result = ftape_mmap(vma)) >= 0) {
198 #ifndef MSYNC_BUG_WAS_FIXED
199                 static struct vm_operations_struct dummy = { NULL, };
200                 vma->vm_ops = &dummy;
201 #endif
202         }
203         current->blocked = old_sigmask; /* restore mask */
204         TRACE_EXIT result;
205 }
206
207 /*      Read from floppy tape device
208  */
209 static ssize_t zft_read(struct file *fp, char __user *buff,
210                         size_t req_len, loff_t *ppos)
211 {
212         int result = -EIO;
213         sigset_t old_sigmask;
214         struct inode *ino = fp->f_dentry->d_inode;
215         TRACE_FUN(ft_t_flow);
216
217         TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len);
218         if (!test_bit(0,&busy_flag)  || iminor(ino) != zft_unit || ft_failure) {
219                 TRACE_ABORT(-EIO, ft_t_err,
220                             "failed: not busy, failure or wrong unit");
221         }
222         old_sigmask = current->blocked; /* save mask */
223         sigfillset(&current->blocked);
224         result = _zft_read(buff, req_len);
225         current->blocked = old_sigmask; /* restore mask */
226         TRACE(ft_t_data_flow, "return with count: %d", result);
227         TRACE_EXIT result;
228 }
229
230 /*      Write to tape device
231  */
232 static ssize_t zft_write(struct file *fp, const char __user *buff,
233                          size_t req_len, loff_t *ppos)
234 {
235         int result = -EIO;
236         sigset_t old_sigmask;
237         struct inode *ino = fp->f_dentry->d_inode;
238         TRACE_FUN(ft_t_flow);
239
240         TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len);
241         if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
242                 TRACE_ABORT(-EIO, ft_t_err,
243                             "failed: not busy, failure or wrong unit");
244         }
245         old_sigmask = current->blocked; /* save mask */
246         sigfillset(&current->blocked);
247         result = _zft_write(buff, req_len);
248         current->blocked = old_sigmask; /* restore mask */
249         TRACE(ft_t_data_flow, "return with count: %d", result);
250         TRACE_EXIT result;
251 }
252
253 /*                    END OF VFS INTERFACE 
254  *          
255  *****************************************************************************/
256
257 /*  driver/module initialization
258  */
259
260 /*  the compression module has to call this function to hook into the zftape 
261  *  code
262  */
263 int zft_cmpr_register(struct zft_cmpr_ops *new_ops)
264 {
265         TRACE_FUN(ft_t_flow);
266         
267         if (zft_cmpr_ops != NULL) {
268                 TRACE_EXIT -EBUSY;
269         } else {
270                 zft_cmpr_ops = new_ops;
271                 TRACE_EXIT 0;
272         }
273 }
274
275 /*  lock the zft-compressor() module.
276  */
277 int zft_cmpr_lock(int try_to_load)
278 {
279         if (zft_cmpr_ops == NULL) {
280 #ifdef CONFIG_KMOD
281                 if (try_to_load) {
282                         request_module("zft-compressor");
283                         if (zft_cmpr_ops == NULL) {
284                                 return -ENOSYS;
285                         }
286                 } else {
287                         return -ENOSYS;
288                 }
289 #else
290                 return -ENOSYS;
291 #endif
292         }
293         (*zft_cmpr_ops->lock)();
294         return 0;
295 }
296
297 #ifdef CONFIG_ZFT_COMPRESSOR
298 extern int zft_compressor_init(void);
299 #endif
300
301 /*  Called by modules package when installing the driver or by kernel
302  *  during the initialization phase
303  */
304 int __init zft_init(void)
305 {
306         int i;
307         TRACE_FUN(ft_t_flow);
308
309 #ifdef MODULE
310         printk(KERN_INFO ZFTAPE_VERSION "\n");
311         if (TRACE_LEVEL >= ft_t_info) {
312                 printk(
313 KERN_INFO
314 "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
315 KERN_INFO
316 "vfs interface for ftape floppy tape driver.\n"
317 KERN_INFO
318 "Support for QIC-113 compatible volume table, dynamic memory allocation\n"
319 KERN_INFO
320 "and builtin compression (lzrw3 algorithm).\n");
321         }
322 #else /* !MODULE */
323         /* print a short no-nonsense boot message */
324         printk(KERN_INFO ZFTAPE_VERSION "\n");
325 #endif /* MODULE */
326         TRACE(ft_t_info, "zft_init @ 0x%p", zft_init);
327         TRACE(ft_t_info,
328               "installing zftape VFS interface for ftape driver ...");
329         TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
330
331         zft_class = class_create(THIS_MODULE, "zft");
332         for (i = 0; i < 4; i++) {
333                 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
334                 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
335                 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
336                 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
337                 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
338                 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
339         }
340
341 #ifdef CONFIG_ZFT_COMPRESSOR
342         (void)zft_compressor_init();
343 #endif
344         zft_status = ftape_get_status(); /*  fetch global data of ftape 
345                                           *  hardware driver 
346                                           */
347         TRACE_EXIT 0;
348 }
349
350
351 /* Called by modules package when removing the driver 
352  */
353 static void zft_exit(void)
354 {
355         int i;
356         TRACE_FUN(ft_t_flow);
357
358         if (unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) {
359                 TRACE(ft_t_warn, "failed");
360         } else {
361                 TRACE(ft_t_info, "successful");
362         }
363         for (i = 0; i < 4; i++) {
364                 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i));
365                 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4));
366                 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16));
367                 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20));
368                 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32));
369                 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36));
370         }
371         class_destroy(zft_class);
372         zft_uninit_mem(); /* release remaining memory, if any */
373         printk(KERN_INFO "zftape successfully unloaded.\n");
374         TRACE_EXIT;
375 }
376
377 module_init(zft_init);
378 module_exit(zft_exit);