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