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