summaryrefslogtreecommitdiff
path: root/usr/src/man/man4i/mtio.4i
blob: 93db7028c7d34d24c66c27909c5e1f8dac87735f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
.\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved
.\" Copyright 2018, Joyent, Inc.
.\" The contents of this file are subject to the terms of the
.\" Common Development and Distribution License (the "License").
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
.\" or http://www.opensolaris.org/os/licensing.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
.\" When distributing Covered Code, include this CDDL HEADER in each
.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE.
.\" If applicable, add the following below this CDDL HEADER, with the
.\" fields enclosed by brackets "[]" replaced with your own identifying
.\" information: Portions Copyright [yyyy] [name of copyright owner]
.Dd August 28, 2021
.Dt MTIO 4I
.Os
.Sh NAME
.Nm mtio
.Nd general magnetic tape interface
.Sh SYNOPSIS
.In sys/types.h
.In sys/ioctl.h
.In sys/mtio.h
.Sh DESCRIPTION
1/2", 1/4", 4mm, and 8mm magnetic tape drives all share the same general
character device interface.
.Pp
There are two types of tape records: data records and end-of-file (EOF)
records.
.Sy EOF
records are also known as tape marks and file marks.
A record is separated by interrecord (or tape) gaps on a tape.
.Pp
End-of-recorded-media (EOM) is indicated by two
.Sy EOF
marks on 1/2\(dq tape; by one
.Sy EOF
mark on 1/4\(dq, 4mm, and 8mm cartridge tapes.
.Ss "1/2\(dq Reel Tape"
Data bytes are recorded in parallel onto the 9-track tape.
Since it is a
variable-length tape device, the number of bytes in a physical record may vary.
.Pp
The recording formats available (check specific tape drive) are 800
.Sy BPI ,
1600
.Sy BPI ,
6250
.Sy BPI ,
and data compression.
Actual storage capacity is a function of the recording format and the length of the tape reel.
For example, using a 2400 foot tape, 20 Mbyte can be stored using 800
.Sy BPI ,
40 Mbyte using 1600
.Sy BPI ,
140 Mbyte using 6250
.Sy BPI ,
or up to 700 Mbyte using data compression.
.Ss "1/4\(dq Cartridge Tape"
Data is recorded serially onto 1/4\(dq cartridge tape.
The number of bytes per
record is determined by the physical record size of the device.
The I/O request
size must be a multiple of the physical record size of the device.
For
.Sy QIC-11 ,
.Sy QIC-24 ,
and
.Sy QIC-150
tape drives, the block size is 512 bytes.
.Pp
The records are recorded on tracks in a serpentine motion.
As one track is
completed, the drive switches to the next and begins writing in the opposite
direction, eliminating the wasted motion of rewinding.
Each file, including the last, ends with one file mark.
.Pp
Storage capacity is based on the number of tracks the drive is capable of
recording.
For example, 4-track drives can only record 20 Mbyte of data on a
450 foot tape; 9-track drives can record up to 45 Mbyte of data on a tape of
the same length.
.Sy QIC-11
is the only tape format available for 4-track
tape drives.
In contrast, 9-track tape drives can use either
.Sy QIC-24
or
.Sy QIC-11 .
Storage capacity is not appreciably affected by using either format.
.Sy QIC-24
is preferable to
.Sy QIC-11
because it records a
reference signal to mark the position of the first track on the tape, and each
block has a unique block number.
.Pp
The
.Sy QIC-150
tape drives require
.Sy DC-6150
(or equivalent) tape cartridges for writing.
However, they can read other tape cartridges in
.Sy QIC-11 ,
.Sy QIC-24 ,
or
.Sy QIC-120
tape formats.
.Ss "8mm Cartridge Tape"
Data is recorded serially onto 8mm helical scan cartridge tape.
Since it is a
variable-length tape device, the number of bytes in a physical record may
vary.
The recording formats available (check specific tape drive) are standard
2Gbyte, 5Gbyte, and compressed format.
.Ss "4mm DAT Tape"
Data is recorded either in Digital Data Storage (DDS) tape format or in Digital
Data Storage, Data Compressed (DDS-DC) tape format.
Since it is a
variable-length tape device, the number of bytes in a physical record may vary.
The recording formats available are standard 2Gbyte and compressed format.
.Ss "Persistent Error Handling"
Persistent error handling is a modification of the current error handling
behaviors, BSD and SVR4.
With persistent error handling enabled, all tape
operations after an error or exception will return immediately with an error.
Persistent error handling can be most useful with asynchronous tape operations
that use the
.Xr aioread 3C
and
.Xr aiowrite 3C
functions.
.Pp
To enable persistent error handling, the ioctl
.Dv MTIOCPERSISTENT
must be issued.
If this ioctl succeeds, then persistent error handling is enabled and
changes the current error behavior.
This ioctl will fail if the device driver
does not support persistent error handling.
.Pp
With persistent error handling enabled, all tape operations after an exception
or error will return with the same error as the first command that failed; the
operations will not be executed.
An exception is some event that might stop
normal tape operations, such as an End Of File (EOF) mark or an End Of Tape
(EOT) mark.
An example of an error is a media error.
The
.Dv MTIOCLRERR
ioctl must be issued to allow normal tape operations to continue and to clear
the error.
.Pp
Disabling persistent error handling returns the error behavior to normal SVR4
error handling, and will not occur until all outstanding operations are
completed.
Applications should wait for all outstanding operations to complete
before disabling persistent error handling.
Closing the device will also
disable persistent error handling and clear any errors or exceptions.
.Pp
The
.Sx Read Operation
and
.Sx Write Operation
subsections contain more pertinent information regarding persistent error handling.
.Ss "Read Operation"
The
.Xr read 2
function reads the next record on the tape.
The record size is passed back as the number of bytes read, provided it is not
greater than the number requested.
When a tape mark or end of data is read, a zero byte count is
returned; all successive reads after the zero read will return an error and
.Va errno
will be set to
.Er EIO .
To move to the next file, an
.Dv MTFSF
ioctl can be issued before or after the read causing the error.
This error
handling behavior is different from the older
.Sy BSD
behavior, where another read will fetch the first record of the next tape file.
If the
.Sy BSD
behavior is required, device names containing the letter
.Ql b
(for
.Sy BSD
behavior) in the final component should be used.
If persistent error handling
was enabled with either the BSD or SVR4 tape device behavior, all operations
after this read error will return
.Er EIO
errors until the
.Dv MTIOCLRERR
ioctl is issued.
An
.Dv MTFSF
ioctl can then he issued.
.Pp
Two successful successive reads that both return zero byte counts indicate
.Sy EOM
on the tape.
No further reading should be performed past the
.Sy EOM .
.Pp
Fixed-length I/O tape devices require the number of bytes read to be a multiple
of the physical record size.
For example, 1/4\(dq cartridge tape devices only read
multiples of 512 bytes.
If the blocking factor is greater than 64,512 bytes
(minphys limit), fixed-length I/O tape devices read multiple records.
.Pp
Most tape devices which support variable-length I/O operations may read a range
of 1 to 65,535 bytes.
If the record size exceeds 65,535 bytes, the driver reads
multiple records to satisfy the request.
These multiple records are limited to
65,534 bytes.
Newer variable-length tape drivers may relax the above limitation
and allow applications to read record sizes larger than 65,534.
Refer to the
specific tape driver man page for details.
.Pp
Reading past logical
.Sy EOT
is transparent to the user.
A read operation
should never hit physical EOT.
.Pp
Read requests that are lesser than a physical tape record are not allowed.
Appropriate error is returned.
.Ss "Write Operation"
The
.Xr write 2
function writes the next record on the tape.
The record has
the same length as the given buffer.
.Pp
Writing is allowed on 1/4" tape at either the beginning of tape or after the
last written file on the tape.
With the Exabyte 8200, data may be appended only
at the beginning of tape, before a filemark, or after the last written file on
the tape.
.Pp
Writing is not so restricted on 1/2\(dq, 4mm, and the other 8mm cartridge tape
drives.
Care should be used when appending files onto 1/2\(dq reel tape devices,
since an extra file mark is appended after the last file to mark the
.Sy EOM .
This extra file mark must be overwritten to prevent the creation of a null file.
To facilitate write append operations, a space to the
.Sy EOM
ioctl is provided.
Care should be taken when overwriting records; the erase head is just
forward of the write head and any following records will also be erased.
.Pp
Fixed-length I/O tape devices require the number of bytes written to be a
multiple of the physical record size.
For example, 1/4\(dq cartridge tape devices
only write multiples of 512 bytes.
.Pp
Fixed-length I/O tape devices write multiple records if the blocking factor is
greater than 64,512 bytes (minphys limit).
These multiple writes are limited to
64,512 bytes.
For example, if a write request is issued for 65,536 bytes using
a 1/4\(dq cartridge tape, two writes are issued; the first for 64,512 bytes and
the second for 1024 bytes.
.Pp
Most tape devices which support variable-length I/O operations may write a
range of 1 to 65,535 bytes.
If the record size exceeds 65,535 bytes, the driver
writes multiple records to satisfy the request.
These multiple records are
limited to 65,534 bytes.
As an example, if a write request for 65,540 bytes is
issued, two records are written; one for 65,534 bytes followed by another
record for 6 bytes.
Newer variable-length tape drivers may relax the above
limitation and allow applications to write record sizes larger than 65,534.
effer to the specific tape driver man page for details.
.Pp
When logical
.Sy EOT
is encountered during a write, that write operation
completes and the number of bytes successfully transferred is returned (note
that a 'short write' may have occurred and not all the requested bytes would
have been transferred.
The actual amount of data written will depend on the
type of device being used).
The next write will return a zero byte count.
A third write will successfully transfer some bytes (as indicated by the
returned byte count, which again could be a short write); the fourth will
transfer zero bytes, and so on, until the physical
.Sy EOT
is reached and all writes will
fail with
.Er EIO .
.Pp
When logical
.Sy EOT
is encountered with persistent error handling enabled,
the current write may complete or be a short write.
The next write will return a zero byte count.
At this point an application should act appropriately for
end of tape cleanup or issue yet another write, which will return the error
.Er ENOSPC .
After clearing the exception with
.Dv MTIOCLRERR ,
the next write will succeed (possibly short), followed by another zero byte
write count, and then another
.Er ENOSPC
error.
.Pp
Allowing writes after
.Sy EOT
has been encountered enables the flushing of buffers.
However, it is strongly recommended to terminate the writing and close
the file as soon as possible.
.Pp
Seeks are ignored in tape I/O.
.Ss "Close Operation"
Magnetic tapes are rewound when closed, except when the "no-rewind" devices
have been specified.
The names of no-rewind device files use the letter
.Ql n
as the end of the final component.
The no-rewind version of
.Pa /dev/rmt/0l
is
.Pa /dev/rmt/0ln .
In case of error for a no-rewind device, the next open rewinds the device.
.Pp
If the driver was opened for reading and a no-rewind device has been specified,
the close advances the tape past the next filemark (unless the current file
position is at
.Sy EOM ) ,
leaving the tape correctly positioned to read the first record of the next file.
However, if the tape is at the first record of a
file it doesn't advance again to the first record of the next file.
These semantics are different from the older
.Sy BSD
behavior.
If
.Sy BSD
behavior is required where no implicit space operation is executed on close,
the non-rewind device name containing the letter
.Ql b
(for
.Sy BSD
behavior) in the final component should be specified.
.Pp
If data was written, a file mark is automatically written by the driver upon
close.
If the rewinding device was specified, the tape will be rewound after
the file mark is written.
If the user wrote a file mark prior to closing, then
no file mark is written upon close.
If a file positioning ioctl, like rewind,
is issued after writing, a file mark is written before repositioning the tape.
.Pp
All buffers are flushed on closing a tape device.
Hence, it is strongly recommended that the application wait for all buffers to
be flushed before closing the device.
This can be done by writing a filemark via
.Dv MTWEOF ,
even with a zero count.
.Pp
Note that for 1/2\(dq reel tape devices, two file marks are written to mark the
.Sy EOM
before rewinding or performing a file positioning ioctl.
If the user
wrote a file mark before closing a 1/2\(dq reel tape device, the driver will
always write a file mark before closing to insure that the end of recorded
media is marked properly.
If the non-rewinding device was specified, two file
marks are written and the tape is left positioned between the two so that the
second one is overwritten on a subsequent
.Xr open 2
and
.Xr write 2 .
.Pp
If no data was written and the driver was opened for
.Sy WRITE-ONLY
access, one or two file marks are written, thus creating a null file.
.Pp
After closing the device, persistent error handling will be disabled and any
error or exception will be cleared.
.Sh IOCTLS
Not all devices support all
.Sy ioctls .
The driver returns an
.Er ENOTTY
error on unsupported ioctls.
.Pp
The following structure definitions for magnetic tape
.Xr ioctl 2
commands are from
.In sys/mtio.h .
.Pp
The minor device byte structure is:
.Bd -literal
15      7      6          5          4         3          2       1   0
________________________________________________________________________
Unit #       BSD      Reserved   Density   Density   No rewind    Unit #
Bits 7-15   behavior              Select    Select    on Close    Bits 0-1
.Ed
.Bd -literal
/*
 * Layout of minor device byte:
 */
#define MTUNIT(dev)   (((minor(dev) & 0xff80) >> 5) + (minor(dev) & 0x3))
#define MT_NOREWIND	(1 <<2)
#define MT_DENSITY_MASK	(3 <<3)
#define MT_DENSITY1	(0 <<3)	/* Lowest density/format */
#define MT_DENSITY2	(1 <<3)
#define MT_DENSITY3	(2 <<3)
#define MT_DENSITY4	(3 <<3)	/* Highest density/format */
#define MTMINOR(unit)	(((unit & 0x7fc) << 5) + (unit & 0x3))
#define MT_BSD	(1 <<6)         /* BSD behavior on close */

/* Structure for MTIOCTOP - magnetic tape operation command */

struct mtop {
  short   mt_op;       /* operation */
  daddr_t mt_count;    /* number of operations */
};

/* Structure for MTIOCLTOP - magnetic tape operation command */
Works exactly like MTIOCTOP except passes 64 bit mt_count values.
struct mtlop {
        short           mt_op;
        short           pad[3];
        int64_t         mt_count;
};
.Ed
.Pp
The following operations of
.Dv MTIOCTOP
and
.Dv MTIOCLTOP
ioctls are supported:
.Pp
.Bl -tag -width MTIOCGETERROR -compact -offset 2n
.It Dv MTWEOF
Write an end-of-file record
.It Dv MTFSF
Forward space over file mark
.It Dv MTBSF
Backward space over file mark (1/2", 8mm only)
.It Dv MTFSR
Forward space to inter-record gap
.It Dv MTBSR
Backward space to inter-record gap
.It Dv MTREW
Rewind
.It Dv MTOFFL
Rewind and take the drive off-line
.It Dv MTNOP
No operation, sets status only
.It Dv MTRETEN
Retension the tape (cartridge tape only)
.It Dv MTERASE
Erase the entire tape and rewind
.It Dv MTEOM
Position to EOM
.It Dv MTNBSF
Backward space file to beginning of file
.It Dv MTSRSZ
Set record size
.It Dv MTGRSZ
Get record size
.It Dv MTTELL
Get current position
.It Dv MTSEEK
Go to requested position
.It Dv MTFSSF
Forward to requested number of sequential file marks
.It Dv MTBSSF
Backward to requested number of sequential file marks
.It Dv MTLOCK
Prevent media removal
.It Dv MTUNLOCK
Allow media removal
.It Dv MTLOAD
Load the next tape cartridge into the tape drive
.It Dv MTIOCGETERROR
Retrieve error records from the st driver
.El
.Bd -literal -offset 2n
/* structure for MTIOCGET - magnetic tape get status command */

struct  mtget {
  short	mt_type;	/* type of magtape device */

  /* the following two registers are device dependent */
  short  mt_dsreg;      /* "drive status" register */
  short  mt_erreg;      /* "error" register */

  /* optional error info.  */
  daddr_t   mt_resid;   /* residual count */
  daddr_t   mt_fileno;  /* file number of current position */
  daddr_t   mt_blkno;   /* block number of current position */
  ushort_t  mt_flags;
  short     mt_bf;      /* optimum blocking factor */
};

/* structure for MTIOCGETDRIVETYPE - get tape config data command */
struct mtdrivetype_request {
  int  size;
  struct  mtdrivetype	*mtdtp;
};
struct mtdrivetype {
  char    name[64];                  /* Name, for debug */
  char    vid[25];                   /* Vendor id and product id */
  char    type;                      /* Drive type for driver */
  int     bsize;                     /* Block size */
  int     options;                   /* Drive options */
  int     max_rretries;              /* Max read retries */
  int     max_wretries;              /* Max write retries */
  uchar_t densities[MT_NDENSITIES];  /* density codes,low->hi */
  uchar_t default_density;           /* Default density chosen */
  uchar_t speeds[MT_NSPEEDS];        /* speed codes, low->hi */
  ushort_t non_motion_timeout;       /* Seconds for non-motion */
  ushort_t io_timeout;               /* Seconds for data to from tape */
  ushort_t rewind_timeout;           /* Seconds to rewind */
  ushort_t space_timeout;            /* Seconds to space anywhere */
  ushort_t load_timeout;             /* Seconds to load tape and ready */
  ushort_t unload_timeout;           /* Seconds to unload */
  ushort_t erase_timeout;            /* Seconds to do long erase */
};
.Ed
.Bd -literal -offset 2n
/* structure for MTIOCGETPOS and MTIOCRESTPOS - get/set tape position */
/*
 * eof/eot/eom codes.
 */
 typedef enum {
       ST_NO_EOF,
       ST_EOF_PENDING,         /* filemark pending */
       ST_EOF,                 /* at filemark */
       ST_EOT_PENDING,         /* logical eot pend.  */
       ST_EOT,                 /* at logical eot */
       ST_EOM,                 /* at physical eot */
       ST_WRITE_AFTER_EOM      /* flag allowing writes after EOM */
} pstatus;

typedef enum { invalid, legacy, logical } posmode;

typedef struct tapepos {
   uint64_t lgclblkno;	/* Blks from start of partition */
   int32_t fileno;	/* Num. of current file */
   int32_t blkno;	/* Blk  number in current file */
   int32_t partition;	/* Current partition */
   pstatus eof;         /* eof states */
   posmode pmode;	/* which pos. data is valid */
   char    pad[4];
} tapepos_t;
.Ed
.Pp
.Bd -ragged -compact
If the
.Fa pmode
is legacy,
.Fa fileno
and
.Fa blkno
fields are valid.
.Pp
If the
.Fa pmode
is logical,
.Fa lgclblkno
field is valid.
.Ed
.Pp
The
.Dv MTWEOF
ioctl is used for writing file marks to tape.
Not only does
this signify the end of a file, but also usually has the side effect of
flushing all buffers in the tape drive to the tape medium.
A zero count
.Dv MTWEOF
will just flush all the buffers and will not write any file marks.
Because a successful completion of this tape operation will guarantee that all
tape data has been written to the tape medium, it is recommended that this tape
operation be issued before closing a tape device.
.Pp
When spacing forward over a record (either data or
.Sy EOF ) ,
the tape head is
positioned in the tape gap between the record just skipped and the next record.
When spacing forward over file marks (EOF records), the tape head is positioned
in the tape gap between the next
.Sy EOF
record and the record that follows it.
.Pp
When spacing backward over a record (either data or
.Sy EOF ) ,
the tape head is positioned in the tape gap immediately preceding the tape
record where the tape head is currently positioned.
When spacing backward over file marks (EOF records), the tape head is
positioned in the tape gap preceding the
.Sy EOF .
Thus the next read would fetch the
.Sy EOF .
.Pp
Record skipping does not go past a file mark; file skipping does not go past
the
.Sy EOM .
After an
.Dv MTFSR
<huge number> command, the driver leaves
the tape logically positioned
.Em before
the
.Sy EOF .
A related feature is that
.Sy EOF Ns s
remain pending until the tape is closed.
For example, a program
which first reads all the records of a file up to and including the \fBEOF\fR
and then performs an
.Dv MTFSF
command will leave the tape positioned just
after that same
.Sy EOF ,
rather than skipping the next file.
.Pp
The
.Dv MTNBSF
and
.Dv MTFSF
operations are inverses.
Thus, an
.Dq Dv MTFSF \(mi1
is equivalent to an
.Dq Dv MTNBSF 1 .
An
.Dq Dv MTNBSF 0
is the same as
.Dq Dv MTFSF 0 ;
both position the tape device at the beginning of the current file.
.Pp
.Dv MTBSF
moves the tape backwards by file marks.
The tape position will end
on the beginning of the tape side of the desired file mark.
An
.Dq Dv MTBSF 0
will position the tape at the end of the current file, before the filemark.
.Pp
.Dv MTBSR
and
.Dv MTFSR
operations perform much like space file operations,
except that they move by records instead of files.
Variable-length I/O devices
(1/2\(dq reel, for example) space actual records; fixed-length I/O devices space
physical records (blocks).
1/4\(dq cartridge tape, for example, spaces 512 byte
physical records.
The status ioctl residual count contains the number of files
or records not skipped.
.Pp
.Dv MTFSSF
and
.Dv MTBSSF
space forward or backward, respectively, to the next
occurrence of the requested number of file marks, one following another.
If there are more sequential file marks on tape than were requested, it spaces
over the requested number and positions after the requested file mark.
Note that not all drives support this command and if a request is sent to a
drive that does not,
.Er ENOTTY
is returned.
.Pp
.Dv MTOFFL
rewinds and, if appropriate, takes the device off-line by unloading the tape.
It is recommended that the device be closed after offlining
and then re-opened after a tape has been inserted to facilitate portability to
other platforms and other operating systems.
Attempting to re-open the device
with no tape will result in an error unless the
.Dv O_NDELAY
flag is used.
.Po
See
.Xr open 2 .
.Pc
.Pp
The
.Dv MTRETEN
retension ioctl applies only to 1/4\(dq cartridge tape devices.
It is used to restore tape tension, improving the tape's soft error rate after
extensive start-stop operations or long-term storage.
.Pp
.Dv MTERASE
rewinds the tape, erases it completely, and returns to the
beginning of tape.
Erasing may take a long time depending on the device and/or
tapes.
For time details, refer to the drive specific manual.
.Pp
.Dv MTEOM
positions the tape at a location just after the last file written
on the tape.
For 1/4\(dq cartridge and 8mm tape, this is after the last file mark
on the tape.
For 1/2\(dq reel tape, this is just after the first file mark but
before the second (and last) file mark on the tape.
Additional files can then
be appended onto the tape from that point.
.Pp
Note the difference between
.Dv MTBSF
(backspace over file mark) and
.Dv MTNBSF
(backspace file to beginning of file).
The former moves the tape
backward until it crosses an
.Sy EOF
mark, leaving the tape positioned
.Em before
the file mark.
The latter leaves the tape positioned
.Em after
the file mark.
Hence,
.Dq Dv MTNBSF n
is equivalent to
.Dq Dv MTBSF (n+1)
followed by
.Dq Dv MTFSF 1 .
The 1/4\(dq cartridge tape devices do not support
.Dv MTBSF .
.Pp
.Dv MTSRSZ
and
.Dv MTGRSZ
are used to set and get fixed record lengths.
The
.Dv MTSRSZ
ioctl allows variable length and fixed length tape drives that
support multiple record sizes to set the record length.
The
.Fa mt_count
field of the
.Vt mtop
struct is used to pass the record size to/from the
.Xr st 4D
driver.
A value of
.Ql 0
indicates variable record size.
The
.Dv MTSRSZ
ioctl makes a variable-length tape device behave like a
fixed-length tape device.
Refer to the specific tape driver man page for
details.
.Pp
.Dv MTLOAD
loads the next tape cartridge into the tape drive.
This is generally only used with stacker and tower type tape drives which handle
multiple tapes per tape drive.
A tape device without a tape inserted can be
opened with the
.Dv O_NDELAY
flag, in order to execute this operation.
.Pp
.Dv MTIOCGETERROR
allows user-level applications to retrieve error records
from the
.Xr st 4D
driver.
An error record consists of the SCSI command cdb
which causes the error and a
.Xr scsi_arq_status 9S
structure if available.
The user-level application is responsible for allocating and releasing the
memory for
.Fa mtee_cdb_buf
and
.Fa scsi_arq_status of each
.Vt mterror_entry .
Before issuing the ioctl, the
.Fa mtee_arq_status_len
value should be at least equal to
.Ql sizeof (struct scsi_arq_status) .
If more sense data than the size of
.Xr scsi_arq_status 9S
is desired, the
.Fa mtee_arq_status_len
may be larger than
.Ql sizeof (struct scsi_arq_status)
by the amount of additional extended sense data desired.
The
.Fa es_add_len
field of
.Xr scsi_extended_sense 9S
can be used to determine the amount of valid sense data returned by the device.
.Pp
The
.Dv MTIOCGET
get status
.Xr ioctl 2
call returns the drive ID
.Pq Fa mt_type ,
sense key error
.Pq Fa mt_erreg ,
file number
.Pq Fa mt_fileno ,
optimum blocking factor
.Pq Fa mt_bf
and record number
.Pq Fa mt_blkno
of the last error.
The residual count
.Pq Fa mt_resid
is set to the number of bytes not transferred or files/records not spaced.
The flags word
.Pq Fa mt_flags
contains information indicating if the device is SCSI, if the device is a reel
device and whether the device supports absolute file positioning.
The
.Fa mt_flags
also indicates if the device is requesting cleaning media be used, whether the
device is capable of reporting the requirement of cleaning media and if the
currently loaded media is WORM (Write Once Read Many) media.
.Pp
Note \(em When tape alert cleaning is managed by the st driver, the tape
target driver may continue to return a
.Dq drive needs cleaning
status unless an
.Dv MTIOCGE
.Xr ioctl 2
call is made while the cleaning media is in the drive.
.Pp
The
.Dv MTIOCGETDRIVETYPE
get drivetype ioctl call returns the name of the
tape drive as defined in
.Pa st.conf
.Pq Fa name ,
Vendor
.Sy ID
and model
.Pq Fa product ,
.Sy ID
.Pq Fa vid ,
type of tape device
.Pq Fa type ,
block size
.Pq Fa size ,
drive options
.Pq Fa options ,
maximum read retry count
.Pq Fa max_rretries ,
maximum write retry count
.Pq Fa max_wretries ,
densities supported by the drive
.Pq Fa densities ,
and default density of the tape drive
.Pq Fa default_density .
.Pp
The
.Dv MTIOCGETPOS
ioctl returns the current tape position of the drive.
It is returned in struct tapepos as defined in
.Pa /usr/include/sys/scsi/targets/stdef.h .
.Pp
The
.Dv MTIOCRESTPOS
ioctl restores a saved position from the
.Dv MTIOCGETPOS .
.Ss "Persistent Error Handling IOCTLs and Asynchronous Tape Operations"
.Bl -tag -width MTIOCPERSISTENTSTATUS -compact
.It Dv MTIOCPERSISTENT
enables/disables persistent error handling
.It Dv MTIOCPERSISTENTSTATUS
queries for persistent error handling
.It Dv MTIOCLRERR
clears persistent error handling
.It Dv MTIOCGUARANTEEDORDER
checks whether driver guarantees order of I/O's
.El
.Pp
The
.Dv MTIOCPERSISTENT
ioctl enables or disables persistent error handling.
It takes as an argument a pointer to an integer that turns it either on or off.
If the ioctl succeeds, the desired operation was successful.
It will wait for
all outstanding I/O's to complete before changing the persistent error handling
status.
For example,
.Bd -literal -offset 2n
int on = 1;
ioctl(fd, MTIOCPERSISTENT, &on);
int off = 0;
ioctl(fd, MTIOCPERSISTENT, &off);
.Ed
.Pp
The
.Dv MTIOCPERSISTENTSTATUS
ioctl enables or disables persistent error
handling.
It takes as an argument a pointer to an integer inserted by the
driver.
The integer can be either 1 if persistent error handling is
.Sq on ,
or 0 if persistent error handling is
.Sq off .
It will not wait for outstanding I/O's.
For example,
.Bd -literal -offset 2n
int query;
ioctl(fd, MTIOCPERSISTENTSTATUS, &query);
.Ed
.Pp
The
.Dv MTIOCLRERR
ioctl clears persistent error handling and allows tape
operations to continual normally.
This ioctl requires no argument and will
always succeed, even if persistent error handling has not been enabled.
It will wait for any outstanding I/O's before it clears the error.
.Pp
The
.Dv MTIOCGUARANTEEDORDER
ioctl is used to determine whether the driver
guarantees the order of I/O's.
It takes no argument.
If the ioctl succeeds, the driver will support guaranteed order.
If the driver does not support guaranteed order, then it should not be used
for asynchronous I/O with
.Xr libaio 3lib .
It will wait for any outstanding I/O's before it returns.
For example,
.Bd -literal -offset 2n
ioctl(fd, MTIOCGUARANTEEDORDER)
.Ed
.Pp
See the
.Sx Persistent Error Handling
subsection above for more information on persistent error handling.
.Ss "Asynchronous and State Change IOCTLS"
.Bl -tag -width 1n
.It Dv MTIOCSTATE
This ioctl blocks until the state of the drive, inserted or ejected, is
changed.
The argument is a pointer to a
.Vt enum mtio_state ,
whose possible enumerations are listed below.
The initial value should be either the last reported state of the drive, or
.Dv MTIO_NONE .
Upon return, the
enum pointed to by the argument is updated with the current state of the drive.
.Bd -literal -offset 2n
enum mtio_state {
    MTIO_NONE      /* Return tape's current state */
    MTIO_EJECTED   /* Tape state is "ejected" */
    MTIO_INSERTED  /* Tape state is "inserted" */
};
.Ed
.El
.Pp
When using asynchronous operations, most ioctls will wait for all outstanding
commands to complete before they are executed.
.Ss "IOCTLS for Multi-initiator Configurations"
.Bl -tag -width MTIOCFORCERESERVE -compact
.It Dv MTIOCRESERVE
reserve the tape drive
.It Dv MTIOCRELEASE
revert back to the default behavior of reserve on open/release on close
.It Dv MTIOCFORCERESERVE
reserve the tape unit by breaking reservation held by another host
.El
.Pp
The
.Dv MTIOCRESERVE
ioctl reserves the tape drive such that it does not
release the tape drive at close.
This changes the default behavior of releasing the device upon close.
Reserving the tape drive that is already reserved has no effect.
For example,
.Bd -literal -offset 2n
ioctl(fd, MTIOCRESERVE);
.Ed
.Pp
The
.Dv MTIOCRELEASE
ioctl reverts back to the default behavior of reserve on
open/release on close operation, and a release will occur during the next
close.
Releasing the tape drive that is already released has no effect.
For example,
.Bd -literal -offset 2n
ioctl(fd, MTIOCRELEASE);
.Ed
.Pp
The
.Dv MTIOCFORCERESERVE
ioctl breaks a reservation held by another host, interrupting any I/O in
progress by that other host, and then reserves the tape unit.
This ioctl can be executed only with super-user privileges.
It is recommended to open the tape device in
.Dv O_NDELAY
mode when this ioctl needs to be executed, otherwise the open will fail if
another host indeed has it reserved.
For example,
.Bd -literal -offset 2n
ioctl(fd, MTIOCFORCERESERVE);
.Ed
.Ss "IOCTLS for Handling Tape Configuration Options"
.Bl -tag -width MTIOCREADIGNOREEOFS
.It Dv MTIOCSHORTFMK
enables/disables support for writing short filemarks.
This is specific to Exabyte drives.
.It Dv MTIOCREADIGNOREILI
enables/disables suppress incorrect length indicator (SILI) support during reads
.It Dv MTIOCREADIGNOREEOFS
enables/disables support for reading past two EOF marks which otherwise indicate
End-Of-recording-Media (EOM) in the case of 1/2\(dq reel tape drives
.El
.Pp
The
.Dv MTIOCSHORTFMK
ioctl enables or disables support for short filemarks.
This ioctl is only applicable to Exabyte drives which support short filemarks.
As an argument, it takes a pointer to an integer.
If 0 (zero) is the specified integer, then long filemarks will be written.
If 1 is the specified integer, then short filemarks will be written.
The specified tape behavior will be in effect until the device is closed.
.Pp
For example:
.Bd -literal -offset 2n
int on = 1;
int off = 0;
/* enable short filemarks */
ioctl(fd, MTIOSHORTFMK, &on);
/* disable short filemarks */
ioctl(fd, MTIOCSHORTFMK, &off);
.Ed
.Pp
Tape drives which do not support short filemarks will return an
.Va errno
of
.Er ENOTTY .
.Pp
The
.Dv MTIOCREADIGNOREILI
ioctl enables or disables the suppress incorrect
length indicator (SILI) support during reads.
As an argument, it takes a pointer to an integer.
If 0 (zero) is the specified integer, SILI will not be
used during reads and incorrect length indicator will not be suppressed.
If 1 is the specified integer, SILI will be used during reads and incorrect
length indicator will be suppressed.
The specified tape behavior will be in effect until the device is closed.
.Pp
For example:
.Bd -literal -offset 2n
int on = 1;
int off = 0;
ioctl(fd, MTIOREADIGNOREILI, &on);
ioctl(fd, MTIOREADIGNOREILI, &off);
.Ed
.Pp
The
.Dv MTIOCREADIGNOREEOFS
ioctl enables or disables support for reading
past double EOF marks which otherwise indicate End-Of-recorded-media (EOM) in
the case of 1/2\(dq reel tape drives.
As an argument, it takes a pointer to an integer.
If 0 (zero) is the specified integer, then double EOF marks indicate
End-Of-recorded-media (EOM).
If 1 is the specified integer, the double EOF marks no longer indicate EOM,
thus allowing applications to read past two EOF marks.
In this case it is the responsibility of the application to detect
End-Of-recorded-media (EOM).
The specified tape behavior will be in effect until the device is closed.
.Pp
For example:
.Bd -literal -offset 2n
int on = 1;
int off = 0;
ioctl(fd, MTIOREADIGNOREEOFS, &on);
ioctl(fd, MTIOREADIGNOREEOFS, &off);
.Ed
.Pp
Tape drives other than 1/2\(dq reel tapes will return an
.Va errno
of
.Er ENOTTY .
.Sh FILES
.Pa /dev/rmt/ Ns Ao unit number Ac \
    Ns Ao density Ac \
    Ns Bo Ao BSD behavior Ac Bc \
    Ns Bo Ao no rewind Ac Bc
.Pp
Where
.Aq density
can be
.Ql l ,
.Ql m ,
.Ql h ,
.Ql u/c
(low, medium, high, ultra/compressed, respectively), the
.Aq BSD behavior
option is
.Ql b , and the
.Aq no rewind
option is
.Ql n .
.Pp
For example,
.Pa /dev/rmt/0hbn
specifies unit 0, high density,
.Sy BSD
behavior and no rewind.
.Sh EXAMPLES
.Bl -inset
.It Sy Example 1
Tape Positioning and Tape Drives
.Pp
Suppose you have written three files to the non-rewinding 1/2\(dq tape device,
.Pa /dev/rmt/0ln ,
and that you want to go back and
.Xr dd 8
the second file off the tape.
The commands to do this are:
.Bd -literal -offset 2n
mt -F /dev/rmt/0lbn bsf 3
mt -F /dev/rmt/0lbn fsf 1
dd if=/dev/rmt/0ln
.Ed
.Pp
To accomplish the same tape positioning in a C program, followed by a get
status ioctl:
.Bd -literal -offset 2n
struct mtop mt_command;
struct mtget mt_status;
mt_command.mt_op = MTBSF;
mt_command.mt_count = 3;
ioctl(fd, MTIOCTOP, &mt_command);
mt_command.mt_op = MTFSF;
mt_command.mt_count = 1;
ioctl(fd, MTIOCTOP, &mt_command);
ioctl(fd, MTIOCGET, (char *)&mt_status);
.Ed
.Pp
or
.Bd -literal -offset 2n
mt_command.mt_op = MTNBSF;
mt_command.mt_count = 2;
ioctl(fd, MTIOCTOP, &mt_command);
ioctl(fd, MTIOCGET, (char *)&mt_status);
.Ed
.Pp
To get information about the tape drive:
.Bd -literal -offset 2n
struct mtdrivetype mtdt;
struct mtdrivetype_request mtreq;
mtreq.size = sizeof(struct mtdrivetype);
mtreq.mtdtp = &mtdt;
ioctl(fd, MTIOCGETDRIVETYPE, &mtreq);
.Ed
.El
.Sh SEE ALSO
.Xr mt 1 ,
.Xr tar 1 ,
.Xr open 2 ,
.Xr read 2 ,
.Xr write 2 ,
.Xr aioread 3C ,
.Xr aiowrite 3C ,
.Xr ar.h 3HEAD ,
.Xr st 4D ,
.Xr dd 8
.Pp
.%T 1/4 Inch Tape Drive Tutorial