xref: /linux/drivers/s390/char/tape_std.c (revision 6f7e6393d1ce636bb7ec77a7fe7b77458fddf701)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *    standard tape device functions for ibm tapes.
4  *
5  *  S390 and zSeries version
6  *    Copyright IBM Corp. 2001, 2002
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  *		 Stefan Bader <shbader@de.ibm.com>
12  */
13 
14 #define pr_fmt(fmt) "tape: " fmt
15 
16 #include <linux/export.h>
17 #include <linux/stddef.h>
18 #include <linux/kernel.h>
19 #include <linux/bio.h>
20 #include <linux/timer.h>
21 
22 #include <asm/types.h>
23 #include <asm/idals.h>
24 #include <asm/ebcdic.h>
25 
26 #define TAPE_DBF_AREA	tape_core_dbf
27 
28 #include "tape.h"
29 #include "tape_std.h"
30 
31 /*
32  * tape_std_assign
33  */
34 static void
35 tape_std_assign_timeout(struct timer_list *t)
36 {
37 	struct tape_request *	request = timer_container_of(request, t,
38 								  timer);
39 	struct tape_device *	device = request->device;
40 	int rc;
41 
42 	BUG_ON(!device);
43 
44 	DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n",
45 			device->cdev_id);
46 	rc = tape_cancel_io(device, request);
47 	if(rc)
48 		DBF_EVENT(3, "(%08x): Assign timeout: Cancel failed with rc = "
49 			  "%i\n", device->cdev_id, rc);
50 }
51 
52 int
53 tape_std_assign(struct tape_device *device)
54 {
55 	int                  rc;
56 	struct tape_request *request;
57 
58 	request = tape_alloc_request(2, 11);
59 	if (IS_ERR(request))
60 		return PTR_ERR(request);
61 
62 	request->op = TO_ASSIGN;
63 	tape_ccw_cc(request->cpaddr, ASSIGN, 11, request->cpdata);
64 	tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
65 
66 	/*
67 	 * The assign command sometimes blocks if the device is assigned
68 	 * to another host (actually this shouldn't happen but it does).
69 	 * So we set up a timeout for this call.
70 	 */
71 	timer_setup(&request->timer, tape_std_assign_timeout, 0);
72 	mod_timer(&request->timer, jiffies + msecs_to_jiffies(2000));
73 
74 	rc = tape_do_io_interruptible(device, request);
75 
76 	timer_delete_sync(&request->timer);
77 
78 	if (rc != 0) {
79 		DBF_EVENT(3, "%08x: assign failed - device might be busy\n",
80 			device->cdev_id);
81 	} else {
82 		DBF_EVENT(3, "%08x: Tape assigned\n", device->cdev_id);
83 	}
84 	tape_free_request(request);
85 	return rc;
86 }
87 
88 /*
89  * tape_std_unassign
90  */
91 int
92 tape_std_unassign (struct tape_device *device)
93 {
94 	int                  rc;
95 	struct tape_request *request;
96 
97 	if (device->tape_state == TS_NOT_OPER) {
98 		DBF_EVENT(3, "(%08x): Can't unassign device\n",
99 			device->cdev_id);
100 		return -EIO;
101 	}
102 
103 	request = tape_alloc_request(2, 11);
104 	if (IS_ERR(request))
105 		return PTR_ERR(request);
106 
107 	request->op = TO_UNASSIGN;
108 	tape_ccw_cc(request->cpaddr, UNASSIGN, 11, request->cpdata);
109 	tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
110 
111 	if ((rc = tape_do_io(device, request)) != 0) {
112 		DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id);
113 	} else {
114 		DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id);
115 	}
116 	tape_free_request(request);
117 	return rc;
118 }
119 
120 /*
121  * Read block id.
122  */
123 int
124 tape_std_read_block_id(struct tape_device *device, __u64 *id)
125 {
126 	struct tape_request *request;
127 	int rc;
128 
129 	request = tape_alloc_request(3, 8);
130 	if (IS_ERR(request))
131 		return PTR_ERR(request);
132 	request->op = TO_RBI;
133 	/* setup ccws */
134 	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
135 	tape_ccw_cc(request->cpaddr + 1, READ_BLOCK_ID, 8, request->cpdata);
136 	tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
137 	/* execute it */
138 	rc = tape_do_io(device, request);
139 	if (rc == 0)
140 		/* Get result from read buffer. */
141 		*id = *(__u64 *) request->cpdata;
142 	tape_free_request(request);
143 	return rc;
144 }
145 
146 int
147 tape_std_terminate_write(struct tape_device *device)
148 {
149 	int rc;
150 
151 	if(device->required_tapemarks == 0)
152 		return 0;
153 
154 	DBF_LH(5, "tape%d: terminate write %dxEOF\n", device->first_minor,
155 		device->required_tapemarks);
156 
157 	rc = tape_mtop(device, MTWEOF, device->required_tapemarks);
158 	if (rc)
159 		return rc;
160 
161 	device->required_tapemarks = 0;
162 	return tape_mtop(device, MTBSR, 1);
163 }
164 
165 /*
166  * MTLOAD: Loads the tape.
167  * The default implementation just wait until the tape medium state changes
168  * to MS_LOADED.
169  */
170 int
171 tape_std_mtload(struct tape_device *device, int count)
172 {
173 	return wait_event_interruptible(device->state_change_wq,
174 		(device->medium_state == MS_LOADED));
175 }
176 
177 /*
178  * MTSETBLK: Set block size.
179  */
180 int
181 tape_std_mtsetblk(struct tape_device *device, int count)
182 {
183 	int rc;
184 
185 	DBF_LH(6, "tape_std_mtsetblk(%d)\n", count);
186 	if (count <= 0) {
187 		/*
188 		 * Just set block_size to 0. tapechar_read/tapechar_write
189 		 * will realloc the idal buffer if a bigger one than the
190 		 * current is needed.
191 		 */
192 		device->char_data.block_size = 0;
193 		return 0;
194 	}
195 
196 	rc = tape_check_idalbuffer(device, count);
197 	if (rc)
198 		return rc;
199 
200 	device->char_data.block_size = count;
201 	DBF_LH(6, "new blocksize is %d\n", device->char_data.block_size);
202 
203 	return 0;
204 }
205 
206 /*
207  * MTRESET: Set block size to 0.
208  */
209 int
210 tape_std_mtreset(struct tape_device *device, int count)
211 {
212 	DBF_EVENT(6, "TCHAR:devreset:\n");
213 	device->char_data.block_size = 0;
214 	return 0;
215 }
216 
217 /*
218  * MTFSF: Forward space over 'count' file marks. The tape is positioned
219  * at the EOT (End of Tape) side of the file mark.
220  */
221 int
222 tape_std_mtfsf(struct tape_device *device, int mt_count)
223 {
224 	struct tape_request *request;
225 	struct ccw1 *ccw;
226 
227 	request = tape_alloc_request(mt_count + 2, 0);
228 	if (IS_ERR(request))
229 		return PTR_ERR(request);
230 	request->op = TO_FSF;
231 	/* setup ccws */
232 	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
233 			  device->modeset_byte);
234 	ccw = tape_ccw_repeat(ccw, FORSPACEFILE, mt_count);
235 	ccw = tape_ccw_end(ccw, NOP, 0, NULL);
236 
237 	/* execute it */
238 	return tape_do_io_free(device, request);
239 }
240 
241 /*
242  * MTFSR: Forward space over 'count' tape blocks (blocksize is set
243  * via MTSETBLK.
244  */
245 int
246 tape_std_mtfsr(struct tape_device *device, int mt_count)
247 {
248 	struct tape_request *request;
249 	struct ccw1 *ccw;
250 	int rc;
251 
252 	request = tape_alloc_request(mt_count + 2, 0);
253 	if (IS_ERR(request))
254 		return PTR_ERR(request);
255 	request->op = TO_FSB;
256 	/* setup ccws */
257 	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
258 			  device->modeset_byte);
259 	ccw = tape_ccw_repeat(ccw, FORSPACEBLOCK, mt_count);
260 	ccw = tape_ccw_end(ccw, NOP, 0, NULL);
261 
262 	/* execute it */
263 	rc = tape_do_io(device, request);
264 	if (rc == 0 && request->rescnt > 0) {
265 		DBF_LH(3, "FSR over tapemark\n");
266 		rc = 1;
267 	}
268 	tape_free_request(request);
269 
270 	return rc;
271 }
272 
273 /*
274  * MTBSR: Backward space over 'count' tape blocks.
275  * (blocksize is set via MTSETBLK.
276  */
277 int
278 tape_std_mtbsr(struct tape_device *device, int mt_count)
279 {
280 	struct tape_request *request;
281 	struct ccw1 *ccw;
282 	int rc;
283 
284 	request = tape_alloc_request(mt_count + 2, 0);
285 	if (IS_ERR(request))
286 		return PTR_ERR(request);
287 	request->op = TO_BSB;
288 	/* setup ccws */
289 	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
290 			  device->modeset_byte);
291 	ccw = tape_ccw_repeat(ccw, BACKSPACEBLOCK, mt_count);
292 	ccw = tape_ccw_end(ccw, NOP, 0, NULL);
293 
294 	/* execute it */
295 	rc = tape_do_io(device, request);
296 	if (rc == 0 && request->rescnt > 0) {
297 		DBF_LH(3, "BSR over tapemark\n");
298 		rc = 1;
299 	}
300 	tape_free_request(request);
301 
302 	return rc;
303 }
304 
305 /*
306  * MTWEOF: Write 'count' file marks at the current position.
307  */
308 int
309 tape_std_mtweof(struct tape_device *device, int mt_count)
310 {
311 	struct tape_request *request;
312 	struct ccw1 *ccw;
313 
314 	request = tape_alloc_request(mt_count + 2, 0);
315 	if (IS_ERR(request))
316 		return PTR_ERR(request);
317 	request->op = TO_WTM;
318 	/* setup ccws */
319 	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
320 			  device->modeset_byte);
321 	ccw = tape_ccw_repeat(ccw, WRITETAPEMARK, mt_count);
322 	ccw = tape_ccw_end(ccw, NOP, 0, NULL);
323 
324 	/* execute it */
325 	return tape_do_io_free(device, request);
326 }
327 
328 /*
329  * MTBSFM: Backward space over 'count' file marks.
330  * The tape is positioned at the BOT (Begin Of Tape) side of the
331  * last skipped file mark.
332  */
333 int
334 tape_std_mtbsfm(struct tape_device *device, int mt_count)
335 {
336 	struct tape_request *request;
337 	struct ccw1 *ccw;
338 
339 	request = tape_alloc_request(mt_count + 2, 0);
340 	if (IS_ERR(request))
341 		return PTR_ERR(request);
342 	request->op = TO_BSF;
343 	/* setup ccws */
344 	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
345 			  device->modeset_byte);
346 	ccw = tape_ccw_repeat(ccw, BACKSPACEFILE, mt_count);
347 	ccw = tape_ccw_end(ccw, NOP, 0, NULL);
348 
349 	/* execute it */
350 	return tape_do_io_free(device, request);
351 }
352 
353 /*
354  * MTBSF: Backward space over 'count' file marks. The tape is positioned at
355  * the EOT (End of Tape) side of the last skipped file mark.
356  */
357 int
358 tape_std_mtbsf(struct tape_device *device, int mt_count)
359 {
360 	struct tape_request *request;
361 	struct ccw1 *ccw;
362 	int rc;
363 
364 	request = tape_alloc_request(mt_count + 2, 0);
365 	if (IS_ERR(request))
366 		return PTR_ERR(request);
367 	request->op = TO_BSF;
368 	/* setup ccws */
369 	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
370 			  device->modeset_byte);
371 	ccw = tape_ccw_repeat(ccw, BACKSPACEFILE, mt_count);
372 	ccw = tape_ccw_end(ccw, NOP, 0, NULL);
373 	/* execute it */
374 	rc = tape_do_io_free(device, request);
375 	if (rc == 0) {
376 		rc = tape_mtop(device, MTFSR, 1);
377 		if (rc > 0)
378 			rc = 0;
379 	}
380 	return rc;
381 }
382 
383 /*
384  * MTFSFM: Forward space over 'count' file marks.
385  * The tape is positioned at the BOT (Begin Of Tape) side
386  * of the last skipped file mark.
387  */
388 int
389 tape_std_mtfsfm(struct tape_device *device, int mt_count)
390 {
391 	struct tape_request *request;
392 	struct ccw1 *ccw;
393 	int rc;
394 
395 	request = tape_alloc_request(mt_count + 2, 0);
396 	if (IS_ERR(request))
397 		return PTR_ERR(request);
398 	request->op = TO_FSF;
399 	/* setup ccws */
400 	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
401 			  device->modeset_byte);
402 	ccw = tape_ccw_repeat(ccw, FORSPACEFILE, mt_count);
403 	ccw = tape_ccw_end(ccw, NOP, 0, NULL);
404 	/* execute it */
405 	rc = tape_do_io_free(device, request);
406 	if (rc == 0) {
407 		rc = tape_mtop(device, MTBSR, 1);
408 		if (rc > 0)
409 			rc = 0;
410 	}
411 
412 	return rc;
413 }
414 
415 /*
416  * MTREW: Rewind the tape.
417  */
418 int
419 tape_std_mtrew(struct tape_device *device, int mt_count)
420 {
421 	struct tape_request *request;
422 
423 	request = tape_alloc_request(3, 0);
424 	if (IS_ERR(request))
425 		return PTR_ERR(request);
426 	request->op = TO_REW;
427 	/* setup ccws */
428 	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
429 		    device->modeset_byte);
430 	tape_ccw_cc(request->cpaddr + 1, REWIND, 0, NULL);
431 	tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
432 
433 	/* execute it */
434 	return tape_do_io_free(device, request);
435 }
436 
437 /*
438  * MTOFFL: Rewind the tape and put the drive off-line.
439  * Implement 'rewind unload'
440  */
441 int
442 tape_std_mtoffl(struct tape_device *device, int mt_count)
443 {
444 	struct tape_request *request;
445 
446 	request = tape_alloc_request(3, 0);
447 	if (IS_ERR(request))
448 		return PTR_ERR(request);
449 	request->op = TO_RUN;
450 	/* setup ccws */
451 	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
452 	tape_ccw_cc(request->cpaddr + 1, REWIND_UNLOAD, 0, NULL);
453 	tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
454 
455 	/* execute it */
456 	return tape_do_io_free(device, request);
457 }
458 
459 /*
460  * MTNOP: 'No operation'.
461  */
462 int
463 tape_std_mtnop(struct tape_device *device, int mt_count)
464 {
465 	struct tape_request *request;
466 
467 	request = tape_alloc_request(2, 0);
468 	if (IS_ERR(request))
469 		return PTR_ERR(request);
470 	request->op = TO_NOP;
471 	/* setup ccws */
472 	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
473 	tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
474 	/* execute it */
475 	return tape_do_io_free(device, request);
476 }
477 
478 /*
479  * MTEOM: positions at the end of the portion of the tape already used
480  * for recordind data. MTEOM positions after the last file mark, ready for
481  * appending another file.
482  */
483 int
484 tape_std_mteom(struct tape_device *device, int mt_count)
485 {
486 	int rc;
487 
488 	/*
489 	 * Seek from the beginning of tape (rewind).
490 	 */
491 	if ((rc = tape_mtop(device, MTREW, 1)) < 0)
492 		return rc;
493 
494 	/*
495 	 * The logical end of volume is given by two sewuential tapemarks.
496 	 * Look for this by skipping to the next file (over one tapemark)
497 	 * and then test for another one (fsr returns 1 if a tapemark was
498 	 * encountered).
499 	 */
500 	do {
501 		if ((rc = tape_mtop(device, MTFSF, 1)) < 0)
502 			return rc;
503 		if ((rc = tape_mtop(device, MTFSR, 1)) < 0)
504 			return rc;
505 	} while (rc == 0);
506 
507 	return tape_mtop(device, MTBSR, 1);
508 }
509 
510 /*
511  * MTRETEN: Retension the tape, i.e. forward space to end of tape and rewind.
512  */
513 int
514 tape_std_mtreten(struct tape_device *device, int mt_count)
515 {
516 	struct tape_request *request;
517 
518 	request = tape_alloc_request(4, 0);
519 	if (IS_ERR(request))
520 		return PTR_ERR(request);
521 	request->op = TO_FSF;
522 	/* setup ccws */
523 	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
524 	tape_ccw_cc(request->cpaddr + 1,FORSPACEFILE, 0, NULL);
525 	tape_ccw_cc(request->cpaddr + 2, NOP, 0, NULL);
526 	tape_ccw_end(request->cpaddr + 3, CCW_CMD_TIC, 0, request->cpaddr);
527 	/* execute it, MTRETEN rc gets ignored */
528 	tape_do_io_interruptible(device, request);
529 	tape_free_request(request);
530 	return tape_mtop(device, MTREW, 1);
531 }
532 
533 /*
534  * MTERASE: erases the tape.
535  */
536 int
537 tape_std_mterase(struct tape_device *device, int mt_count)
538 {
539 	struct tape_request *request;
540 
541 	request = tape_alloc_request(6, 0);
542 	if (IS_ERR(request))
543 		return PTR_ERR(request);
544 	request->op = TO_DSE;
545 	/* setup ccws */
546 	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
547 	tape_ccw_cc(request->cpaddr + 1, REWIND, 0, NULL);
548 	tape_ccw_cc(request->cpaddr + 2, ERASE_GAP, 0, NULL);
549 	tape_ccw_cc(request->cpaddr + 3, DATA_SEC_ERASE, 0, NULL);
550 	tape_ccw_cc(request->cpaddr + 4, REWIND, 0, NULL);
551 	tape_ccw_end(request->cpaddr + 5, NOP, 0, NULL);
552 
553 	/* execute it */
554 	return tape_do_io_free(device, request);
555 }
556 
557 /*
558  * MTUNLOAD: Rewind the tape and unload it.
559  */
560 int
561 tape_std_mtunload(struct tape_device *device, int mt_count)
562 {
563 	return tape_mtop(device, MTOFFL, mt_count);
564 }
565 
566 /*
567  * MTCOMPRESSION: used to enable compression.
568  * Sets the IDRC on/off.
569  */
570 int
571 tape_std_mtcompression(struct tape_device *device, int mt_count)
572 {
573 	struct tape_request *request;
574 
575 	if (mt_count < 0 || mt_count > 1) {
576 		DBF_EXCEPTION(6, "xcom parm\n");
577 		return -EINVAL;
578 	}
579 	request = tape_alloc_request(2, 0);
580 	if (IS_ERR(request))
581 		return PTR_ERR(request);
582 	request->op = TO_NOP;
583 	/* setup ccws */
584 	if (mt_count == 0)
585 		*device->modeset_byte &= ~0x08;
586 	else
587 		*device->modeset_byte |= 0x08;
588 	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
589 	tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
590 	/* execute it */
591 	return tape_do_io_free(device, request);
592 }
593 
594 /*
595  * Read Block
596  */
597 struct tape_request *
598 tape_std_read_block(struct tape_device *device)
599 {
600 	struct tape_request *request;
601 	struct idal_buffer **ibs;
602 	struct ccw1 *ccw;
603 	size_t count;
604 
605 	ibs = device->char_data.ibs;
606 	count = idal_buffer_array_size(ibs);
607 	request = tape_alloc_request(count + 1 /* MODE_SET_DB */, 0);
608 	if (IS_ERR(request)) {
609 		DBF_EXCEPTION(6, "xrbl fail");
610 		return request;
611 	}
612 	request->op = TO_RFO;
613 	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
614 	while (count-- > 1)
615 		ccw = tape_ccw_dc_idal(ccw, READ_FORWARD, *ibs++);
616 	tape_ccw_end_idal(ccw, READ_FORWARD, *ibs);
617 
618 	DBF_EVENT(6, "xrbl ccwg\n");
619 	return request;
620 }
621 
622 /*
623  * Write Block
624  */
625 struct tape_request *
626 tape_std_write_block(struct tape_device *device)
627 {
628 	struct tape_request *request;
629 	struct idal_buffer **ibs;
630 	struct ccw1 *ccw;
631 	size_t count;
632 
633 	count = idal_buffer_array_size(device->char_data.ibs);
634 	request = tape_alloc_request(count + 1 /* MODE_SET_DB */, 0);
635 	if (IS_ERR(request)) {
636 		DBF_EXCEPTION(6, "xwbl fail\n");
637 		return request;
638 	}
639 	request->op = TO_WRI;
640 	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
641 	ibs = device->char_data.ibs;
642 	while (count-- > 1)
643 		ccw = tape_ccw_dc_idal(ccw, WRITE_CMD, *ibs++);
644 	tape_ccw_end_idal(ccw, WRITE_CMD, *ibs);
645 
646 	DBF_EVENT(6, "xwbl ccwg\n");
647 	return request;
648 }
649 
650 /*
651  * This routine is called by frontend after an ENOSP on write
652  */
653 void
654 tape_std_process_eov(struct tape_device *device)
655 {
656 	/*
657 	 * End of volume: We have to backspace the last written record, then
658 	 * we TRY to write a tapemark and then backspace over the written TM
659 	 */
660 	if (tape_mtop(device, MTBSR, 1) == 0 &&
661 	    tape_mtop(device, MTWEOF, 1) == 0) {
662 		tape_mtop(device, MTBSR, 1);
663 	}
664 }
665 
666 EXPORT_SYMBOL(tape_std_assign);
667 EXPORT_SYMBOL(tape_std_unassign);
668 EXPORT_SYMBOL(tape_std_read_block_id);
669 EXPORT_SYMBOL(tape_std_mtload);
670 EXPORT_SYMBOL(tape_std_mtsetblk);
671 EXPORT_SYMBOL(tape_std_mtreset);
672 EXPORT_SYMBOL(tape_std_mtfsf);
673 EXPORT_SYMBOL(tape_std_mtfsr);
674 EXPORT_SYMBOL(tape_std_mtbsr);
675 EXPORT_SYMBOL(tape_std_mtweof);
676 EXPORT_SYMBOL(tape_std_mtbsfm);
677 EXPORT_SYMBOL(tape_std_mtbsf);
678 EXPORT_SYMBOL(tape_std_mtfsfm);
679 EXPORT_SYMBOL(tape_std_mtrew);
680 EXPORT_SYMBOL(tape_std_mtoffl);
681 EXPORT_SYMBOL(tape_std_mtnop);
682 EXPORT_SYMBOL(tape_std_mteom);
683 EXPORT_SYMBOL(tape_std_mtreten);
684 EXPORT_SYMBOL(tape_std_mterase);
685 EXPORT_SYMBOL(tape_std_mtunload);
686 EXPORT_SYMBOL(tape_std_mtcompression);
687 EXPORT_SYMBOL(tape_std_read_block);
688 EXPORT_SYMBOL(tape_std_write_block);
689 EXPORT_SYMBOL(tape_std_process_eov);
690