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