]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/s390/char/tape_std.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6-omap-h63xx.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/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                         dev_name(&device->cdev->dev), 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                         dev_name(&device->cdev->dev));
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                         dev_name(&device->cdev->dev));
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",
124                            dev_name(&device->cdev->dev));
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 (IS_ERR(new))
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                                    dev_name(&device->cdev->dev));
639                 else
640                         PRINT_INFO("(%s) Compression is currently off\n",
641                                    dev_name(&device->cdev->dev));
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         if (mt_count == 0)
652                 *device->modeset_byte &= ~0x08;
653         else
654                 *device->modeset_byte |= 0x08;
655         tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
656         tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
657         /* execute it */
658         return tape_do_io_free(device, request);
659 }
660
661 /*
662  * Read Block
663  */
664 struct tape_request *
665 tape_std_read_block(struct tape_device *device, size_t count)
666 {
667         struct tape_request *request;
668
669         /*
670          * We have to alloc 4 ccws in order to be able to transform request
671          * into a read backward request in error case.
672          */
673         request = tape_alloc_request(4, 0);
674         if (IS_ERR(request)) {
675                 DBF_EXCEPTION(6, "xrbl fail");
676                 return request;
677         }
678         request->op = TO_RFO;
679         tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
680         tape_ccw_end_idal(request->cpaddr + 1, READ_FORWARD,
681                           device->char_data.idal_buf);
682         DBF_EVENT(6, "xrbl ccwg\n");
683         return request;
684 }
685
686 /*
687  * Read Block backward transformation function.
688  */
689 void
690 tape_std_read_backward(struct tape_device *device, struct tape_request *request)
691 {
692         /*
693          * We have allocated 4 ccws in tape_std_read, so we can now
694          * transform the request to a read backward, followed by a
695          * forward space block.
696          */
697         request->op = TO_RBA;
698         tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
699         tape_ccw_cc_idal(request->cpaddr + 1, READ_BACKWARD,
700                          device->char_data.idal_buf);
701         tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL);
702         tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL);
703         DBF_EVENT(6, "xrop ccwg");}
704
705 /*
706  * Write Block
707  */
708 struct tape_request *
709 tape_std_write_block(struct tape_device *device, size_t count)
710 {
711         struct tape_request *request;
712
713         request = tape_alloc_request(2, 0);
714         if (IS_ERR(request)) {
715                 DBF_EXCEPTION(6, "xwbl fail\n");
716                 return request;
717         }
718         request->op = TO_WRI;
719         tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
720         tape_ccw_end_idal(request->cpaddr + 1, WRITE_CMD,
721                           device->char_data.idal_buf);
722         DBF_EVENT(6, "xwbl ccwg\n");
723         return request;
724 }
725
726 /*
727  * This routine is called by frontend after an ENOSP on write
728  */
729 void
730 tape_std_process_eov(struct tape_device *device)
731 {
732         /*
733          * End of volume: We have to backspace the last written record, then
734          * we TRY to write a tapemark and then backspace over the written TM
735          */
736         if (tape_mtop(device, MTBSR, 1) == 0 &&
737             tape_mtop(device, MTWEOF, 1) == 0) {
738                 tape_mtop(device, MTBSR, 1);
739         }
740 }
741
742 EXPORT_SYMBOL(tape_std_assign);
743 EXPORT_SYMBOL(tape_std_unassign);
744 EXPORT_SYMBOL(tape_std_display);
745 EXPORT_SYMBOL(tape_std_read_block_id);
746 EXPORT_SYMBOL(tape_std_mtload);
747 EXPORT_SYMBOL(tape_std_mtsetblk);
748 EXPORT_SYMBOL(tape_std_mtreset);
749 EXPORT_SYMBOL(tape_std_mtfsf);
750 EXPORT_SYMBOL(tape_std_mtfsr);
751 EXPORT_SYMBOL(tape_std_mtbsr);
752 EXPORT_SYMBOL(tape_std_mtweof);
753 EXPORT_SYMBOL(tape_std_mtbsfm);
754 EXPORT_SYMBOL(tape_std_mtbsf);
755 EXPORT_SYMBOL(tape_std_mtfsfm);
756 EXPORT_SYMBOL(tape_std_mtrew);
757 EXPORT_SYMBOL(tape_std_mtoffl);
758 EXPORT_SYMBOL(tape_std_mtnop);
759 EXPORT_SYMBOL(tape_std_mteom);
760 EXPORT_SYMBOL(tape_std_mtreten);
761 EXPORT_SYMBOL(tape_std_mterase);
762 EXPORT_SYMBOL(tape_std_mtunload);
763 EXPORT_SYMBOL(tape_std_mtcompression);
764 EXPORT_SYMBOL(tape_std_read_block);
765 EXPORT_SYMBOL(tape_std_read_backward);
766 EXPORT_SYMBOL(tape_std_write_block);
767 EXPORT_SYMBOL(tape_std_process_eov);