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