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