2 * drivers/s390/char/tape_std.c
3 * standard tape device functions for ibm tapes.
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>
14 #include <linux/stddef.h>
15 #include <linux/kernel.h>
16 #include <linux/bio.h>
17 #include <linux/timer.h>
19 #include <asm/types.h>
20 #include <asm/idals.h>
21 #include <asm/ebcdic.h>
22 #include <asm/tape390.h>
24 #define TAPE_DBF_AREA tape_core_dbf
33 tape_std_assign_timeout(unsigned long data
)
35 struct tape_request
* request
;
36 struct tape_device
* device
;
39 request
= (struct tape_request
*) data
;
40 device
= request
->device
;
43 DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n",
45 rc
= tape_cancel_io(device
, request
);
47 DBF_EVENT(3, "(%s): Assign timeout: Cancel failed with rc = %i\n",
48 dev_name(&device
->cdev
->dev
), rc
);
52 tape_std_assign(struct tape_device
*device
)
55 struct timer_list timeout
;
56 struct tape_request
*request
;
58 request
= tape_alloc_request(2, 11);
60 return PTR_ERR(request
);
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
);
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.
72 timeout
.function
= tape_std_assign_timeout
;
73 timeout
.data
= (unsigned long) request
;
74 timeout
.expires
= jiffies
+ 2 * HZ
;
77 rc
= tape_do_io_interruptible(device
, request
);
82 DBF_EVENT(3, "%08x: assign failed - device might be busy\n",
85 DBF_EVENT(3, "%08x: Tape assigned\n", device
->cdev_id
);
87 tape_free_request(request
);
95 tape_std_unassign (struct tape_device
*device
)
98 struct tape_request
*request
;
100 if (device
->tape_state
== TS_NOT_OPER
) {
101 DBF_EVENT(3, "(%08x): Can't unassign device\n",
106 request
= tape_alloc_request(2, 11);
108 return PTR_ERR(request
);
110 request
->op
= TO_UNASSIGN
;
111 tape_ccw_cc(request
->cpaddr
, UNASSIGN
, 11, request
->cpdata
);
112 tape_ccw_end(request
->cpaddr
+ 1, NOP
, 0, NULL
);
114 if ((rc
= tape_do_io(device
, request
)) != 0) {
115 DBF_EVENT(3, "%08x: Unassign failed\n", device
->cdev_id
);
117 DBF_EVENT(3, "%08x: Tape unassigned\n", device
->cdev_id
);
119 tape_free_request(request
);
124 * TAPE390_DISPLAY: Show a string on the tape display.
127 tape_std_display(struct tape_device
*device
, struct display_struct
*disp
)
129 struct tape_request
*request
;
132 request
= tape_alloc_request(2, 17);
133 if (IS_ERR(request
)) {
134 DBF_EVENT(3, "TAPE: load display failed\n");
135 return PTR_ERR(request
);
137 request
->op
= TO_DIS
;
139 *(unsigned char *) request
->cpdata
= disp
->cntrl
;
140 DBF_EVENT(5, "TAPE: display cntrl=%04x\n", disp
->cntrl
);
141 memcpy(((unsigned char *) request
->cpdata
) + 1, disp
->message1
, 8);
142 memcpy(((unsigned char *) request
->cpdata
) + 9, disp
->message2
, 8);
143 ASCEBC(((unsigned char*) request
->cpdata
) + 1, 16);
145 tape_ccw_cc(request
->cpaddr
, LOAD_DISPLAY
, 17, request
->cpdata
);
146 tape_ccw_end(request
->cpaddr
+ 1, NOP
, 0, NULL
);
148 rc
= tape_do_io_interruptible(device
, request
);
149 tape_free_request(request
);
157 tape_std_read_block_id(struct tape_device
*device
, __u64
*id
)
159 struct tape_request
*request
;
162 request
= tape_alloc_request(3, 8);
164 return PTR_ERR(request
);
165 request
->op
= TO_RBI
;
167 tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1, device
->modeset_byte
);
168 tape_ccw_cc(request
->cpaddr
+ 1, READ_BLOCK_ID
, 8, request
->cpdata
);
169 tape_ccw_end(request
->cpaddr
+ 2, NOP
, 0, NULL
);
171 rc
= tape_do_io(device
, request
);
173 /* Get result from read buffer. */
174 *id
= *(__u64
*) request
->cpdata
;
175 tape_free_request(request
);
180 tape_std_terminate_write(struct tape_device
*device
)
184 if(device
->required_tapemarks
== 0)
187 DBF_LH(5, "tape%d: terminate write %dxEOF\n", device
->first_minor
,
188 device
->required_tapemarks
);
190 rc
= tape_mtop(device
, MTWEOF
, device
->required_tapemarks
);
194 device
->required_tapemarks
= 0;
195 return tape_mtop(device
, MTBSR
, 1);
199 * MTLOAD: Loads the tape.
200 * The default implementation just wait until the tape medium state changes
204 tape_std_mtload(struct tape_device
*device
, int count
)
206 return wait_event_interruptible(device
->state_change_wq
,
207 (device
->medium_state
== MS_LOADED
));
211 * MTSETBLK: Set block size.
214 tape_std_mtsetblk(struct tape_device
*device
, int count
)
216 struct idal_buffer
*new;
218 DBF_LH(6, "tape_std_mtsetblk(%d)\n", count
);
221 * Just set block_size to 0. tapechar_read/tapechar_write
222 * will realloc the idal buffer if a bigger one than the
225 device
->char_data
.block_size
= 0;
228 if (device
->char_data
.idal_buf
!= NULL
&&
229 device
->char_data
.idal_buf
->size
== count
)
230 /* We already have a idal buffer of that size. */
233 if (count
> MAX_BLOCKSIZE
) {
234 DBF_EVENT(3, "Invalid block size (%d > %d) given.\n",
235 count
, MAX_BLOCKSIZE
);
239 /* Allocate a new idal buffer. */
240 new = idal_buffer_alloc(count
, 0);
243 if (device
->char_data
.idal_buf
!= NULL
)
244 idal_buffer_free(device
->char_data
.idal_buf
);
245 device
->char_data
.idal_buf
= new;
246 device
->char_data
.block_size
= count
;
248 DBF_LH(6, "new blocksize is %d\n", device
->char_data
.block_size
);
254 * MTRESET: Set block size to 0.
257 tape_std_mtreset(struct tape_device
*device
, int count
)
259 DBF_EVENT(6, "TCHAR:devreset:\n");
260 device
->char_data
.block_size
= 0;
265 * MTFSF: Forward space over 'count' file marks. The tape is positioned
266 * at the EOT (End of Tape) side of the file mark.
269 tape_std_mtfsf(struct tape_device
*device
, int mt_count
)
271 struct tape_request
*request
;
274 request
= tape_alloc_request(mt_count
+ 2, 0);
276 return PTR_ERR(request
);
277 request
->op
= TO_FSF
;
279 ccw
= tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1,
280 device
->modeset_byte
);
281 ccw
= tape_ccw_repeat(ccw
, FORSPACEFILE
, mt_count
);
282 ccw
= tape_ccw_end(ccw
, NOP
, 0, NULL
);
285 return tape_do_io_free(device
, request
);
289 * MTFSR: Forward space over 'count' tape blocks (blocksize is set
293 tape_std_mtfsr(struct tape_device
*device
, int mt_count
)
295 struct tape_request
*request
;
299 request
= tape_alloc_request(mt_count
+ 2, 0);
301 return PTR_ERR(request
);
302 request
->op
= TO_FSB
;
304 ccw
= tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1,
305 device
->modeset_byte
);
306 ccw
= tape_ccw_repeat(ccw
, FORSPACEBLOCK
, mt_count
);
307 ccw
= tape_ccw_end(ccw
, NOP
, 0, NULL
);
310 rc
= tape_do_io(device
, request
);
311 if (rc
== 0 && request
->rescnt
> 0) {
312 DBF_LH(3, "FSR over tapemark\n");
315 tape_free_request(request
);
321 * MTBSR: Backward space over 'count' tape blocks.
322 * (blocksize is set via MTSETBLK.
325 tape_std_mtbsr(struct tape_device
*device
, int mt_count
)
327 struct tape_request
*request
;
331 request
= tape_alloc_request(mt_count
+ 2, 0);
333 return PTR_ERR(request
);
334 request
->op
= TO_BSB
;
336 ccw
= tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1,
337 device
->modeset_byte
);
338 ccw
= tape_ccw_repeat(ccw
, BACKSPACEBLOCK
, mt_count
);
339 ccw
= tape_ccw_end(ccw
, NOP
, 0, NULL
);
342 rc
= tape_do_io(device
, request
);
343 if (rc
== 0 && request
->rescnt
> 0) {
344 DBF_LH(3, "BSR over tapemark\n");
347 tape_free_request(request
);
353 * MTWEOF: Write 'count' file marks at the current position.
356 tape_std_mtweof(struct tape_device
*device
, int mt_count
)
358 struct tape_request
*request
;
361 request
= tape_alloc_request(mt_count
+ 2, 0);
363 return PTR_ERR(request
);
364 request
->op
= TO_WTM
;
366 ccw
= tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1,
367 device
->modeset_byte
);
368 ccw
= tape_ccw_repeat(ccw
, WRITETAPEMARK
, mt_count
);
369 ccw
= tape_ccw_end(ccw
, NOP
, 0, NULL
);
372 return tape_do_io_free(device
, request
);
376 * MTBSFM: Backward space over 'count' file marks.
377 * The tape is positioned at the BOT (Begin Of Tape) side of the
378 * last skipped file mark.
381 tape_std_mtbsfm(struct tape_device
*device
, int mt_count
)
383 struct tape_request
*request
;
386 request
= tape_alloc_request(mt_count
+ 2, 0);
388 return PTR_ERR(request
);
389 request
->op
= TO_BSF
;
391 ccw
= tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1,
392 device
->modeset_byte
);
393 ccw
= tape_ccw_repeat(ccw
, BACKSPACEFILE
, mt_count
);
394 ccw
= tape_ccw_end(ccw
, NOP
, 0, NULL
);
397 return tape_do_io_free(device
, request
);
401 * MTBSF: Backward space over 'count' file marks. The tape is positioned at
402 * the EOT (End of Tape) side of the last skipped file mark.
405 tape_std_mtbsf(struct tape_device
*device
, int mt_count
)
407 struct tape_request
*request
;
411 request
= tape_alloc_request(mt_count
+ 2, 0);
413 return PTR_ERR(request
);
414 request
->op
= TO_BSF
;
416 ccw
= tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1,
417 device
->modeset_byte
);
418 ccw
= tape_ccw_repeat(ccw
, BACKSPACEFILE
, mt_count
);
419 ccw
= tape_ccw_end(ccw
, NOP
, 0, NULL
);
421 rc
= tape_do_io_free(device
, request
);
423 rc
= tape_mtop(device
, MTFSR
, 1);
431 * MTFSFM: Forward space over 'count' file marks.
432 * The tape is positioned at the BOT (Begin Of Tape) side
433 * of the last skipped file mark.
436 tape_std_mtfsfm(struct tape_device
*device
, int mt_count
)
438 struct tape_request
*request
;
442 request
= tape_alloc_request(mt_count
+ 2, 0);
444 return PTR_ERR(request
);
445 request
->op
= TO_FSF
;
447 ccw
= tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1,
448 device
->modeset_byte
);
449 ccw
= tape_ccw_repeat(ccw
, FORSPACEFILE
, mt_count
);
450 ccw
= tape_ccw_end(ccw
, NOP
, 0, NULL
);
452 rc
= tape_do_io_free(device
, request
);
454 rc
= tape_mtop(device
, MTBSR
, 1);
463 * MTREW: Rewind the tape.
466 tape_std_mtrew(struct tape_device
*device
, int mt_count
)
468 struct tape_request
*request
;
470 request
= tape_alloc_request(3, 0);
472 return PTR_ERR(request
);
473 request
->op
= TO_REW
;
475 tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1,
476 device
->modeset_byte
);
477 tape_ccw_cc(request
->cpaddr
+ 1, REWIND
, 0, NULL
);
478 tape_ccw_end(request
->cpaddr
+ 2, NOP
, 0, NULL
);
481 return tape_do_io_free(device
, request
);
485 * MTOFFL: Rewind the tape and put the drive off-line.
486 * Implement 'rewind unload'
489 tape_std_mtoffl(struct tape_device
*device
, int mt_count
)
491 struct tape_request
*request
;
493 request
= tape_alloc_request(3, 0);
495 return PTR_ERR(request
);
496 request
->op
= TO_RUN
;
498 tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1, device
->modeset_byte
);
499 tape_ccw_cc(request
->cpaddr
+ 1, REWIND_UNLOAD
, 0, NULL
);
500 tape_ccw_end(request
->cpaddr
+ 2, NOP
, 0, NULL
);
503 return tape_do_io_free(device
, request
);
507 * MTNOP: 'No operation'.
510 tape_std_mtnop(struct tape_device
*device
, int mt_count
)
512 struct tape_request
*request
;
514 request
= tape_alloc_request(2, 0);
516 return PTR_ERR(request
);
517 request
->op
= TO_NOP
;
519 tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1, device
->modeset_byte
);
520 tape_ccw_end(request
->cpaddr
+ 1, NOP
, 0, NULL
);
522 return tape_do_io_free(device
, request
);
526 * MTEOM: positions at the end of the portion of the tape already used
527 * for recordind data. MTEOM positions after the last file mark, ready for
528 * appending another file.
531 tape_std_mteom(struct tape_device
*device
, int mt_count
)
536 * Seek from the beginning of tape (rewind).
538 if ((rc
= tape_mtop(device
, MTREW
, 1)) < 0)
542 * The logical end of volume is given by two sewuential tapemarks.
543 * Look for this by skipping to the next file (over one tapemark)
544 * and then test for another one (fsr returns 1 if a tapemark was
548 if ((rc
= tape_mtop(device
, MTFSF
, 1)) < 0)
550 if ((rc
= tape_mtop(device
, MTFSR
, 1)) < 0)
554 return tape_mtop(device
, MTBSR
, 1);
558 * MTRETEN: Retension the tape, i.e. forward space to end of tape and rewind.
561 tape_std_mtreten(struct tape_device
*device
, int mt_count
)
563 struct tape_request
*request
;
566 request
= tape_alloc_request(4, 0);
568 return PTR_ERR(request
);
569 request
->op
= TO_FSF
;
571 tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1, device
->modeset_byte
);
572 tape_ccw_cc(request
->cpaddr
+ 1,FORSPACEFILE
, 0, NULL
);
573 tape_ccw_cc(request
->cpaddr
+ 2, NOP
, 0, NULL
);
574 tape_ccw_end(request
->cpaddr
+ 3, CCW_CMD_TIC
, 0, request
->cpaddr
);
575 /* execute it, MTRETEN rc gets ignored */
576 rc
= tape_do_io_interruptible(device
, request
);
577 tape_free_request(request
);
578 return tape_mtop(device
, MTREW
, 1);
582 * MTERASE: erases the tape.
585 tape_std_mterase(struct tape_device
*device
, int mt_count
)
587 struct tape_request
*request
;
589 request
= tape_alloc_request(6, 0);
591 return PTR_ERR(request
);
592 request
->op
= TO_DSE
;
594 tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1, device
->modeset_byte
);
595 tape_ccw_cc(request
->cpaddr
+ 1, REWIND
, 0, NULL
);
596 tape_ccw_cc(request
->cpaddr
+ 2, ERASE_GAP
, 0, NULL
);
597 tape_ccw_cc(request
->cpaddr
+ 3, DATA_SEC_ERASE
, 0, NULL
);
598 tape_ccw_cc(request
->cpaddr
+ 4, REWIND
, 0, NULL
);
599 tape_ccw_end(request
->cpaddr
+ 5, NOP
, 0, NULL
);
602 return tape_do_io_free(device
, request
);
606 * MTUNLOAD: Rewind the tape and unload it.
609 tape_std_mtunload(struct tape_device
*device
, int mt_count
)
611 return tape_mtop(device
, MTOFFL
, mt_count
);
615 * MTCOMPRESSION: used to enable compression.
616 * Sets the IDRC on/off.
619 tape_std_mtcompression(struct tape_device
*device
, int mt_count
)
621 struct tape_request
*request
;
623 if (mt_count
< 0 || mt_count
> 1) {
624 DBF_EXCEPTION(6, "xcom parm\n");
627 request
= tape_alloc_request(2, 0);
629 return PTR_ERR(request
);
630 request
->op
= TO_NOP
;
633 *device
->modeset_byte
&= ~0x08;
635 *device
->modeset_byte
|= 0x08;
636 tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1, device
->modeset_byte
);
637 tape_ccw_end(request
->cpaddr
+ 1, NOP
, 0, NULL
);
639 return tape_do_io_free(device
, request
);
645 struct tape_request
*
646 tape_std_read_block(struct tape_device
*device
, size_t count
)
648 struct tape_request
*request
;
651 * We have to alloc 4 ccws in order to be able to transform request
652 * into a read backward request in error case.
654 request
= tape_alloc_request(4, 0);
655 if (IS_ERR(request
)) {
656 DBF_EXCEPTION(6, "xrbl fail");
659 request
->op
= TO_RFO
;
660 tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1, device
->modeset_byte
);
661 tape_ccw_end_idal(request
->cpaddr
+ 1, READ_FORWARD
,
662 device
->char_data
.idal_buf
);
663 DBF_EVENT(6, "xrbl ccwg\n");
668 * Read Block backward transformation function.
671 tape_std_read_backward(struct tape_device
*device
, struct tape_request
*request
)
674 * We have allocated 4 ccws in tape_std_read, so we can now
675 * transform the request to a read backward, followed by a
676 * forward space block.
678 request
->op
= TO_RBA
;
679 tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1, device
->modeset_byte
);
680 tape_ccw_cc_idal(request
->cpaddr
+ 1, READ_BACKWARD
,
681 device
->char_data
.idal_buf
);
682 tape_ccw_cc(request
->cpaddr
+ 2, FORSPACEBLOCK
, 0, NULL
);
683 tape_ccw_end(request
->cpaddr
+ 3, NOP
, 0, NULL
);
684 DBF_EVENT(6, "xrop ccwg");}
689 struct tape_request
*
690 tape_std_write_block(struct tape_device
*device
, size_t count
)
692 struct tape_request
*request
;
694 request
= tape_alloc_request(2, 0);
695 if (IS_ERR(request
)) {
696 DBF_EXCEPTION(6, "xwbl fail\n");
699 request
->op
= TO_WRI
;
700 tape_ccw_cc(request
->cpaddr
, MODE_SET_DB
, 1, device
->modeset_byte
);
701 tape_ccw_end_idal(request
->cpaddr
+ 1, WRITE_CMD
,
702 device
->char_data
.idal_buf
);
703 DBF_EVENT(6, "xwbl ccwg\n");
708 * This routine is called by frontend after an ENOSP on write
711 tape_std_process_eov(struct tape_device
*device
)
714 * End of volume: We have to backspace the last written record, then
715 * we TRY to write a tapemark and then backspace over the written TM
717 if (tape_mtop(device
, MTBSR
, 1) == 0 &&
718 tape_mtop(device
, MTWEOF
, 1) == 0) {
719 tape_mtop(device
, MTBSR
, 1);
723 EXPORT_SYMBOL(tape_std_assign
);
724 EXPORT_SYMBOL(tape_std_unassign
);
725 EXPORT_SYMBOL(tape_std_display
);
726 EXPORT_SYMBOL(tape_std_read_block_id
);
727 EXPORT_SYMBOL(tape_std_mtload
);
728 EXPORT_SYMBOL(tape_std_mtsetblk
);
729 EXPORT_SYMBOL(tape_std_mtreset
);
730 EXPORT_SYMBOL(tape_std_mtfsf
);
731 EXPORT_SYMBOL(tape_std_mtfsr
);
732 EXPORT_SYMBOL(tape_std_mtbsr
);
733 EXPORT_SYMBOL(tape_std_mtweof
);
734 EXPORT_SYMBOL(tape_std_mtbsfm
);
735 EXPORT_SYMBOL(tape_std_mtbsf
);
736 EXPORT_SYMBOL(tape_std_mtfsfm
);
737 EXPORT_SYMBOL(tape_std_mtrew
);
738 EXPORT_SYMBOL(tape_std_mtoffl
);
739 EXPORT_SYMBOL(tape_std_mtnop
);
740 EXPORT_SYMBOL(tape_std_mteom
);
741 EXPORT_SYMBOL(tape_std_mtreten
);
742 EXPORT_SYMBOL(tape_std_mterase
);
743 EXPORT_SYMBOL(tape_std_mtunload
);
744 EXPORT_SYMBOL(tape_std_mtcompression
);
745 EXPORT_SYMBOL(tape_std_read_block
);
746 EXPORT_SYMBOL(tape_std_read_backward
);
747 EXPORT_SYMBOL(tape_std_write_block
);
748 EXPORT_SYMBOL(tape_std_process_eov
);