883e2db02bd3c8351e8195b5b45b12e84dd44fbf
[pandora-kernel.git] / drivers / s390 / char / tape_char.c
1 /*
2  *  drivers/s390/char/tape_char.c
3  *    character device frontend for tape device driver
4  *
5  *  S390 and zSeries version
6  *    Copyright IBM Corp. 2001,2006
7  *    Author(s): Carsten Otte <cotte@de.ibm.com>
8  *               Michael Holzheu <holzheu@de.ibm.com>
9  *               Tuan Ngo-Anh <ngoanh@de.ibm.com>
10  *               Martin Schwidefsky <schwidefsky@de.ibm.com>
11  */
12
13 #define KMSG_COMPONENT "tape"
14 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
15
16 #include <linux/module.h>
17 #include <linux/types.h>
18 #include <linux/proc_fs.h>
19 #include <linux/mtio.h>
20 #include <linux/smp_lock.h>
21 #include <linux/compat.h>
22
23 #include <asm/uaccess.h>
24
25 #define TAPE_DBF_AREA   tape_core_dbf
26
27 #include "tape.h"
28 #include "tape_std.h"
29 #include "tape_class.h"
30
31 #define TAPECHAR_MAJOR          0       /* get dynamic major */
32
33 /*
34  * file operation structure for tape character frontend
35  */
36 static ssize_t tapechar_read(struct file *, char __user *, size_t, loff_t *);
37 static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *);
38 static int tapechar_open(struct inode *,struct file *);
39 static int tapechar_release(struct inode *,struct file *);
40 static long tapechar_ioctl(struct file *, unsigned int, unsigned long);
41 #ifdef CONFIG_COMPAT
42 static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long);
43 #endif
44
45 static const struct file_operations tape_fops =
46 {
47         .owner = THIS_MODULE,
48         .read = tapechar_read,
49         .write = tapechar_write,
50         .unlocked_ioctl = tapechar_ioctl,
51 #ifdef CONFIG_COMPAT
52         .compat_ioctl = tapechar_compat_ioctl,
53 #endif
54         .open = tapechar_open,
55         .release = tapechar_release,
56         .llseek = no_llseek,
57 };
58
59 static int tapechar_major = TAPECHAR_MAJOR;
60
61 /*
62  * This function is called for every new tapedevice
63  */
64 int
65 tapechar_setup_device(struct tape_device * device)
66 {
67         char    device_name[20];
68
69         sprintf(device_name, "ntibm%i", device->first_minor / 2);
70         device->nt = register_tape_dev(
71                 &device->cdev->dev,
72                 MKDEV(tapechar_major, device->first_minor),
73                 &tape_fops,
74                 device_name,
75                 "non-rewinding"
76         );
77         device_name[0] = 'r';
78         device->rt = register_tape_dev(
79                 &device->cdev->dev,
80                 MKDEV(tapechar_major, device->first_minor + 1),
81                 &tape_fops,
82                 device_name,
83                 "rewinding"
84         );
85
86         return 0;
87 }
88
89 void
90 tapechar_cleanup_device(struct tape_device *device)
91 {
92         unregister_tape_dev(&device->cdev->dev, device->rt);
93         device->rt = NULL;
94         unregister_tape_dev(&device->cdev->dev, device->nt);
95         device->nt = NULL;
96 }
97
98 static int
99 tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
100 {
101         struct idal_buffer *new;
102
103         if (device->char_data.idal_buf != NULL &&
104             device->char_data.idal_buf->size == block_size)
105                 return 0;
106
107         if (block_size > MAX_BLOCKSIZE) {
108                 DBF_EVENT(3, "Invalid blocksize (%zd > %d)\n",
109                         block_size, MAX_BLOCKSIZE);
110                 return -EINVAL;
111         }
112
113         /* The current idal buffer is not correct. Allocate a new one. */
114         new = idal_buffer_alloc(block_size, 0);
115         if (IS_ERR(new))
116                 return -ENOMEM;
117
118         if (device->char_data.idal_buf != NULL)
119                 idal_buffer_free(device->char_data.idal_buf);
120
121         device->char_data.idal_buf = new;
122
123         return 0;
124 }
125
126 /*
127  * Tape device read function
128  */
129 static ssize_t
130 tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
131 {
132         struct tape_device *device;
133         struct tape_request *request;
134         size_t block_size;
135         int rc;
136
137         DBF_EVENT(6, "TCHAR:read\n");
138         device = (struct tape_device *) filp->private_data;
139
140         /*
141          * If the tape isn't terminated yet, do it now. And since we then
142          * are at the end of the tape there wouldn't be anything to read
143          * anyways. So we return immediatly.
144          */
145         if(device->required_tapemarks) {
146                 return tape_std_terminate_write(device);
147         }
148
149         /* Find out block size to use */
150         if (device->char_data.block_size != 0) {
151                 if (count < device->char_data.block_size) {
152                         DBF_EVENT(3, "TCHAR:read smaller than block "
153                                   "size was requested\n");
154                         return -EINVAL;
155                 }
156                 block_size = device->char_data.block_size;
157         } else {
158                 block_size = count;
159         }
160
161         rc = tapechar_check_idalbuffer(device, block_size);
162         if (rc)
163                 return rc;
164
165 #ifdef CONFIG_S390_TAPE_BLOCK
166         /* Changes position. */
167         device->blk_data.medium_changed = 1;
168 #endif
169
170         DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size);
171         /* Let the discipline build the ccw chain. */
172         request = device->discipline->read_block(device, block_size);
173         if (IS_ERR(request))
174                 return PTR_ERR(request);
175         /* Execute it. */
176         rc = tape_do_io(device, request);
177         if (rc == 0) {
178                 rc = block_size - request->rescnt;
179                 DBF_EVENT(6, "TCHAR:rbytes:  %x\n", rc);
180                 /* Copy data from idal buffer to user space. */
181                 if (idal_buffer_to_user(device->char_data.idal_buf,
182                                         data, rc) != 0)
183                         rc = -EFAULT;
184         }
185         tape_free_request(request);
186         return rc;
187 }
188
189 /*
190  * Tape device write function
191  */
192 static ssize_t
193 tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos)
194 {
195         struct tape_device *device;
196         struct tape_request *request;
197         size_t block_size;
198         size_t written;
199         int nblocks;
200         int i, rc;
201
202         DBF_EVENT(6, "TCHAR:write\n");
203         device = (struct tape_device *) filp->private_data;
204         /* Find out block size and number of blocks */
205         if (device->char_data.block_size != 0) {
206                 if (count < device->char_data.block_size) {
207                         DBF_EVENT(3, "TCHAR:write smaller than block "
208                                   "size was requested\n");
209                         return -EINVAL;
210                 }
211                 block_size = device->char_data.block_size;
212                 nblocks = count / block_size;
213         } else {
214                 block_size = count;
215                 nblocks = 1;
216         }
217
218         rc = tapechar_check_idalbuffer(device, block_size);
219         if (rc)
220                 return rc;
221
222 #ifdef CONFIG_S390_TAPE_BLOCK
223         /* Changes position. */
224         device->blk_data.medium_changed = 1;
225 #endif
226
227         DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size);
228         DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks);
229         /* Let the discipline build the ccw chain. */
230         request = device->discipline->write_block(device, block_size);
231         if (IS_ERR(request))
232                 return PTR_ERR(request);
233         rc = 0;
234         written = 0;
235         for (i = 0; i < nblocks; i++) {
236                 /* Copy data from user space to idal buffer. */
237                 if (idal_buffer_from_user(device->char_data.idal_buf,
238                                           data, block_size)) {
239                         rc = -EFAULT;
240                         break;
241                 }
242                 rc = tape_do_io(device, request);
243                 if (rc)
244                         break;
245                 DBF_EVENT(6, "TCHAR:wbytes: %lx\n",
246                           block_size - request->rescnt);
247                 written += block_size - request->rescnt;
248                 if (request->rescnt != 0)
249                         break;
250                 data += block_size;
251         }
252         tape_free_request(request);
253         if (rc == -ENOSPC) {
254                 /*
255                  * Ok, the device has no more space. It has NOT written
256                  * the block.
257                  */
258                 if (device->discipline->process_eov)
259                         device->discipline->process_eov(device);
260                 if (written > 0)
261                         rc = 0;
262
263         }
264
265         /*
266          * After doing a write we always need two tapemarks to correctly
267          * terminate the tape (one to terminate the file, the second to
268          * flag the end of recorded data.
269          * Since process_eov positions the tape in front of the written
270          * tapemark it doesn't hurt to write two marks again.
271          */
272         if (!rc)
273                 device->required_tapemarks = 2;
274
275         return rc ? rc : written;
276 }
277
278 /*
279  * Character frontend tape device open function.
280  */
281 static int
282 tapechar_open (struct inode *inode, struct file *filp)
283 {
284         struct tape_device *device;
285         int minor, rc;
286
287         DBF_EVENT(6, "TCHAR:open: %i:%i\n",
288                 imajor(filp->f_path.dentry->d_inode),
289                 iminor(filp->f_path.dentry->d_inode));
290
291         if (imajor(filp->f_path.dentry->d_inode) != tapechar_major)
292                 return -ENODEV;
293
294         minor = iminor(filp->f_path.dentry->d_inode);
295         device = tape_find_device(minor / TAPE_MINORS_PER_DEV);
296         if (IS_ERR(device)) {
297                 DBF_EVENT(3, "TCHAR:open: tape_find_device() failed\n");
298                 return PTR_ERR(device);
299         }
300
301         rc = tape_open(device);
302         if (rc == 0) {
303                 filp->private_data = device;
304                 nonseekable_open(inode, filp);
305         } else
306                 tape_put_device(device);
307
308         return rc;
309 }
310
311 /*
312  * Character frontend tape device release function.
313  */
314
315 static int
316 tapechar_release(struct inode *inode, struct file *filp)
317 {
318         struct tape_device *device;
319
320         DBF_EVENT(6, "TCHAR:release: %x\n", iminor(inode));
321         device = (struct tape_device *) filp->private_data;
322
323         /*
324          * If this is the rewinding tape minor then rewind. In that case we
325          * write all required tapemarks. Otherwise only one to terminate the
326          * file.
327          */
328         if ((iminor(inode) & 1) != 0) {
329                 if (device->required_tapemarks)
330                         tape_std_terminate_write(device);
331                 tape_mtop(device, MTREW, 1);
332         } else {
333                 if (device->required_tapemarks > 1) {
334                         if (tape_mtop(device, MTWEOF, 1) == 0)
335                                 device->required_tapemarks--;
336                 }
337         }
338
339         if (device->char_data.idal_buf != NULL) {
340                 idal_buffer_free(device->char_data.idal_buf);
341                 device->char_data.idal_buf = NULL;
342         }
343         tape_release(device);
344         filp->private_data = NULL;
345         tape_put_device(device);
346
347         return 0;
348 }
349
350 /*
351  * Tape device io controls.
352  */
353 static int
354 __tapechar_ioctl(struct tape_device *device,
355                  unsigned int no, unsigned long data)
356 {
357         int rc;
358
359         if (no == MTIOCTOP) {
360                 struct mtop op;
361
362                 if (copy_from_user(&op, (char __user *) data, sizeof(op)) != 0)
363                         return -EFAULT;
364                 if (op.mt_count < 0)
365                         return -EINVAL;
366
367                 /*
368                  * Operations that change tape position should write final
369                  * tapemarks.
370                  */
371                 switch (op.mt_op) {
372                         case MTFSF:
373                         case MTBSF:
374                         case MTFSR:
375                         case MTBSR:
376                         case MTREW:
377                         case MTOFFL:
378                         case MTEOM:
379                         case MTRETEN:
380                         case MTBSFM:
381                         case MTFSFM:
382                         case MTSEEK:
383 #ifdef CONFIG_S390_TAPE_BLOCK
384                                 device->blk_data.medium_changed = 1;
385 #endif
386                                 if (device->required_tapemarks)
387                                         tape_std_terminate_write(device);
388                         default:
389                                 ;
390                 }
391                 rc = tape_mtop(device, op.mt_op, op.mt_count);
392
393                 if (op.mt_op == MTWEOF && rc == 0) {
394                         if (op.mt_count > device->required_tapemarks)
395                                 device->required_tapemarks = 0;
396                         else
397                                 device->required_tapemarks -= op.mt_count;
398                 }
399                 return rc;
400         }
401         if (no == MTIOCPOS) {
402                 /* MTIOCPOS: query the tape position. */
403                 struct mtpos pos;
404
405                 rc = tape_mtop(device, MTTELL, 1);
406                 if (rc < 0)
407                         return rc;
408                 pos.mt_blkno = rc;
409                 if (copy_to_user((char __user *) data, &pos, sizeof(pos)) != 0)
410                         return -EFAULT;
411                 return 0;
412         }
413         if (no == MTIOCGET) {
414                 /* MTIOCGET: query the tape drive status. */
415                 struct mtget get;
416
417                 memset(&get, 0, sizeof(get));
418                 get.mt_type = MT_ISUNKNOWN;
419                 get.mt_resid = 0 /* device->devstat.rescnt */;
420                 get.mt_dsreg = device->tape_state;
421                 /* FIXME: mt_gstat, mt_erreg, mt_fileno */
422                 get.mt_gstat = 0;
423                 get.mt_erreg = 0;
424                 get.mt_fileno = 0;
425                 get.mt_gstat  = device->tape_generic_status;
426
427                 if (device->medium_state == MS_LOADED) {
428                         rc = tape_mtop(device, MTTELL, 1);
429
430                         if (rc < 0)
431                                 return rc;
432
433                         if (rc == 0)
434                                 get.mt_gstat |= GMT_BOT(~0);
435
436                         get.mt_blkno = rc;
437                 }
438
439                 if (copy_to_user((char __user *) data, &get, sizeof(get)) != 0)
440                         return -EFAULT;
441
442                 return 0;
443         }
444         /* Try the discipline ioctl function. */
445         if (device->discipline->ioctl_fn == NULL)
446                 return -EINVAL;
447         return device->discipline->ioctl_fn(device, no, data);
448 }
449
450 static long
451 tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data)
452 {
453         struct tape_device *device;
454         long rc;
455
456         DBF_EVENT(6, "TCHAR:ioct\n");
457
458         device = (struct tape_device *) filp->private_data;
459         mutex_lock(&device->mutex);
460         rc = __tapechar_ioctl(device, no, data);
461         mutex_unlock(&device->mutex);
462         return rc;
463 }
464
465 #ifdef CONFIG_COMPAT
466 static long
467 tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
468 {
469         struct tape_device *device = filp->private_data;
470         int rval = -ENOIOCTLCMD;
471         unsigned long argp;
472
473         /* The 'arg' argument of any ioctl function may only be used for
474          * pointers because of the compat pointer conversion.
475          * Consider this when adding new ioctls.
476          */
477         argp = (unsigned long) compat_ptr(data);
478         if (device->discipline->ioctl_fn) {
479                 mutex_lock(&device->mutex);
480                 rval = device->discipline->ioctl_fn(device, no, argp);
481                 mutex_unlock(&device->mutex);
482                 if (rval == -EINVAL)
483                         rval = -ENOIOCTLCMD;
484         }
485
486         return rval;
487 }
488 #endif /* CONFIG_COMPAT */
489
490 /*
491  * Initialize character device frontend.
492  */
493 int
494 tapechar_init (void)
495 {
496         dev_t   dev;
497
498         if (alloc_chrdev_region(&dev, 0, 256, "tape") != 0)
499                 return -1;
500
501         tapechar_major = MAJOR(dev);
502
503         return 0;
504 }
505
506 /*
507  * cleanup
508  */
509 void
510 tapechar_exit(void)
511 {
512         unregister_chrdev_region(MKDEV(tapechar_major, 0), 256);
513 }