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