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