xref: /openbmc/linux/drivers/s390/char/tape_std.c (revision 8fa5723aa7e053d498336b48448b292fc2e0458b)
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);
768