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