File Index
Files and directories
Sign in
FILE

tape_std.c

File preview with syntax highlighting.

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