mt.c revision 7913
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 351590Srgrimesstatic char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 411590Srgrimesstatic char sccsid[] = "@(#)mt.c 8.1 (Berkeley) 6/6/93"; 421590Srgrimes#endif /* not lint */ 431590Srgrimes 441590Srgrimes/* 451590Srgrimes * mt -- 461590Srgrimes * magnetic tape manipulation program 471590Srgrimes */ 481590Srgrimes#include <sys/types.h> 491590Srgrimes#include <sys/ioctl.h> 501590Srgrimes#include <sys/mtio.h> 511590Srgrimes#include <fcntl.h> 521590Srgrimes#include <errno.h> 531590Srgrimes#include <stdlib.h> 541590Srgrimes#include <stdio.h> 551590Srgrimes#include <ctype.h> 561590Srgrimes#include <string.h> 571590Srgrimes 587913Sjoerg/* the appropriate sections of <sys/mtio.h> are also #ifdef'd for FreeBSD */ 597913Sjoerg#if defined(__FreeBSD__) 607913Sjoerg/* c_flags */ 617913Sjoerg#define NEED_2ARGS 0x01 627913Sjoerg#define ZERO_ALLOWED 0X02 637913Sjoerg#endif /* defined(__FreeBSD__) */ 647913Sjoerg 651590Srgrimesstruct commands { 661590Srgrimes char *c_name; 671590Srgrimes int c_code; 681590Srgrimes int c_ronly; 697913Sjoerg#if defined(__FreeBSD__) 707913Sjoerg int c_flags; 717913Sjoerg#endif /* defined(__FreeBSD__) */ 721590Srgrimes} com[] = { 731590Srgrimes { "bsf", MTBSF, 1 }, 741590Srgrimes { "bsr", MTBSR, 1 }, 751590Srgrimes { "eof", MTWEOF, 0 }, 761590Srgrimes { "fsf", MTFSF, 1 }, 771590Srgrimes { "fsr", MTFSR, 1 }, 781590Srgrimes { "offline", MTOFFL, 1 }, 791590Srgrimes { "rewind", MTREW, 1 }, 801590Srgrimes { "rewoffl", MTOFFL, 1 }, 811590Srgrimes { "status", MTNOP, 1 }, 821590Srgrimes { "weof", MTWEOF, 0 }, 837913Sjoerg#if defined(__FreeBSD__) 847913Sjoerg { "erase", MTERASE, 0 }, 857913Sjoerg { "blocksize", MTSETBSIZ, 0, NEED_2ARGS|ZERO_ALLOWED }, 867913Sjoerg { "density", MTSETDNSTY, 0, NEED_2ARGS|ZERO_ALLOWED }, 877913Sjoerg { "eom", MTEOD, 1 }, 887913Sjoerg { "comp", MTCOMP, 0, NEED_2ARGS|ZERO_ALLOWED }, 897913Sjoerg#endif /* defined(__FreeBSD__) */ 901590Srgrimes { NULL } 911590Srgrimes}; 921590Srgrimes 931590Srgrimesvoid err __P((const char *, ...)); 941590Srgrimesvoid printreg __P((char *, u_int, char *)); 951590Srgrimesvoid status __P((struct mtget *)); 961590Srgrimesvoid usage __P((void)); 977913Sjoerg#if defined (__FreeBSD__) 987913Sjoergvoid st_status (struct mtget *); 997913Sjoerg#endif /* defined (__FreeBSD__) */ 1001590Srgrimes 1011590Srgrimesint 1021590Srgrimesmain(argc, argv) 1031590Srgrimes int argc; 1041590Srgrimes char *argv[]; 1051590Srgrimes{ 1061590Srgrimes register struct commands *comp; 1071590Srgrimes struct mtget mt_status; 1081590Srgrimes struct mtop mt_com; 1091590Srgrimes int ch, len, mtfd; 1101590Srgrimes char *p, *tape; 1111590Srgrimes 1121590Srgrimes if ((tape = getenv("TAPE")) == NULL) 1131590Srgrimes tape = DEFTAPE; 1141590Srgrimes 1151590Srgrimes while ((ch = getopt(argc, argv, "f:t:")) != EOF) 1161590Srgrimes switch(ch) { 1171590Srgrimes case 'f': 1181590Srgrimes case 't': 1191590Srgrimes tape = optarg; 1201590Srgrimes break; 1211590Srgrimes case '?': 1221590Srgrimes default: 1231590Srgrimes usage(); 1241590Srgrimes } 1251590Srgrimes argc -= optind; 1261590Srgrimes argv += optind; 1271590Srgrimes 1281590Srgrimes if (argc < 1 || argc > 2) 1291590Srgrimes usage(); 1301590Srgrimes 1311590Srgrimes len = strlen(p = *argv++); 1321590Srgrimes for (comp = com;; comp++) { 1331590Srgrimes if (comp->c_name == NULL) 1341590Srgrimes err("%s: unknown command", p); 1351590Srgrimes if (strncmp(p, comp->c_name, len) == 0) 1361590Srgrimes break; 1371590Srgrimes } 1387913Sjoerg#if defined(__FreeBSD__) 1397913Sjoerg if((comp->c_flags & NEED_2ARGS) && argc != 2) 1407913Sjoerg usage(); 1417913Sjoerg#endif /* defined(__FreeBSD__) */ 1421590Srgrimes if ((mtfd = open(tape, comp->c_ronly ? O_RDONLY : O_RDWR)) < 0) 1431590Srgrimes err("%s: %s", tape, strerror(errno)); 1441590Srgrimes if (comp->c_code != MTNOP) { 1451590Srgrimes mt_com.mt_op = comp->c_code; 1461590Srgrimes if (*argv) { 1477913Sjoerg#if defined (__FreeBSD__) 1487913Sjoerg /* allow for hex numbers; useful for density */ 1497913Sjoerg mt_com.mt_count = strtol(*argv, &p, 0); 1507913Sjoerg#else 1511590Srgrimes mt_com.mt_count = strtol(*argv, &p, 10); 1527913Sjoerg#endif /* defined(__FreeBSD__) */ 1537913Sjoerg if (mt_com.mt_count <= 1547913Sjoerg#if defined (__FreeBSD__) 1557913Sjoerg ((comp->c_flags & ZERO_ALLOWED)? -1: 0) 1567913Sjoerg#else 1577913Sjoerg 0 1587913Sjoerg#endif /* defined (__FreeBSD__) */ 1597913Sjoerg || *p) 1601590Srgrimes err("%s: illegal count", *argv); 1611590Srgrimes } 1621590Srgrimes else 1631590Srgrimes mt_com.mt_count = 1; 1641590Srgrimes if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) 1651590Srgrimes err("%s: %s: %s", tape, comp->c_name, strerror(errno)); 1661590Srgrimes } else { 1671590Srgrimes if (ioctl(mtfd, MTIOCGET, &mt_status) < 0) 1681590Srgrimes err("%s", strerror(errno)); 1691590Srgrimes status(&mt_status); 1701590Srgrimes } 1711590Srgrimes exit (0); 1721590Srgrimes /* NOTREACHED */ 1731590Srgrimes} 1741590Srgrimes 1751590Srgrimes#ifdef vax 1761590Srgrimes#include <vax/mba/mtreg.h> 1771590Srgrimes#include <vax/mba/htreg.h> 1781590Srgrimes 1791590Srgrimes#include <vax/uba/utreg.h> 1801590Srgrimes#include <vax/uba/tmreg.h> 1811590Srgrimes#undef b_repcnt /* argh */ 1821590Srgrimes#include <vax/uba/tsreg.h> 1831590Srgrimes#endif 1841590Srgrimes 1851590Srgrimes#ifdef sun 1861590Srgrimes#include <sundev/tmreg.h> 1871590Srgrimes#include <sundev/arreg.h> 1881590Srgrimes#endif 1891590Srgrimes 1901590Srgrimes#ifdef tahoe 1911590Srgrimes#include <tahoe/vba/cyreg.h> 1921590Srgrimes#endif 1931590Srgrimes 1941590Srgrimesstruct tape_desc { 1951590Srgrimes short t_type; /* type of magtape device */ 1961590Srgrimes char *t_name; /* printing name */ 1971590Srgrimes char *t_dsbits; /* "drive status" register */ 1981590Srgrimes char *t_erbits; /* "error" register */ 1991590Srgrimes} tapes[] = { 2001590Srgrimes#ifdef vax 2011590Srgrimes { MT_ISTS, "ts11", 0, TSXS0_BITS }, 2021590Srgrimes { MT_ISHT, "tm03", HTDS_BITS, HTER_BITS }, 2031590Srgrimes { MT_ISTM, "tm11", 0, TMER_BITS }, 2041590Srgrimes { MT_ISMT, "tu78", MTDS_BITS, 0 }, 2051590Srgrimes { MT_ISUT, "tu45", UTDS_BITS, UTER_BITS }, 2061590Srgrimes#endif 2071590Srgrimes#ifdef sun 2081590Srgrimes { MT_ISCPC, "TapeMaster", TMS_BITS, 0 }, 2091590Srgrimes { MT_ISAR, "Archive", ARCH_CTRL_BITS, ARCH_BITS }, 2101590Srgrimes#endif 2111590Srgrimes#ifdef tahoe 2121590Srgrimes { MT_ISCY, "cipher", CYS_BITS, CYCW_BITS }, 2131590Srgrimes#endif 2147913Sjoerg#if defined (__FreeBSD__) 2157913Sjoerg /* 2167913Sjoerg * XXX This is terrific. The st driver reports the tape drive 2177913Sjoerg * as 0x7 (MT_ISAR - Sun/Archive compatible); the wt driver 2187913Sjoerg * either reports MT_ISVIPER1 for an Archive tape, or 0x11 2197913Sjoerg * (MT_ISMFOUR) for other tapes. 2207913Sjoerg * XXX for the wt driver, rely on it behaving like a "standard" 2217913Sjoerg * magtape driver. 2227913Sjoerg */ 2237913Sjoerg { MT_ISAR, "SCSI tape drive", 0, 0 }, 2247913Sjoerg { MT_ISVIPER1, "Archive Viper", 0, 0 }, 2257913Sjoerg { MT_ISMFOUR, "Wangtek", 0, 0 }, 2267913Sjoerg#endif /* defined (__FreeBSD__) */ 2271590Srgrimes { 0 } 2281590Srgrimes}; 2291590Srgrimes 2301590Srgrimes/* 2311590Srgrimes * Interpret the status buffer returned 2321590Srgrimes */ 2331590Srgrimesvoid 2341590Srgrimesstatus(bp) 2351590Srgrimes register struct mtget *bp; 2361590Srgrimes{ 2371590Srgrimes register struct tape_desc *mt; 2381590Srgrimes 2391590Srgrimes for (mt = tapes;; mt++) { 2401590Srgrimes if (mt->t_type == 0) { 2411590Srgrimes (void)printf("%d: unknown tape drive type\n", 2421590Srgrimes bp->mt_type); 2431590Srgrimes return; 2441590Srgrimes } 2451590Srgrimes if (mt->t_type == bp->mt_type) 2461590Srgrimes break; 2471590Srgrimes } 2487913Sjoerg#if defined (__FreeBSD__) 2497913Sjoerg if(mt->t_type == MT_ISAR) 2507913Sjoerg st_status(bp); 2517913Sjoerg else { 2527913Sjoerg#endif /* defined (__FreeBSD__) */ 2531590Srgrimes (void)printf("%s tape drive, residual=%d\n", mt->t_name, bp->mt_resid); 2541590Srgrimes printreg("ds", bp->mt_dsreg, mt->t_dsbits); 2551590Srgrimes printreg("\ner", bp->mt_erreg, mt->t_erbits); 2561590Srgrimes (void)putchar('\n'); 2577913Sjoerg#if defined (__FreeBSD__) 2587913Sjoerg } 2597913Sjoerg#endif /* defined (__FreeBSD__) */ 2601590Srgrimes} 2611590Srgrimes 2621590Srgrimes/* 2631590Srgrimes * Print a register a la the %b format of the kernel's printf. 2641590Srgrimes */ 2651590Srgrimesvoid 2661590Srgrimesprintreg(s, v, bits) 2671590Srgrimes char *s; 2681590Srgrimes register u_int v; 2691590Srgrimes register char *bits; 2701590Srgrimes{ 2711590Srgrimes register int i, any = 0; 2721590Srgrimes register char c; 2731590Srgrimes 2741590Srgrimes if (bits && *bits == 8) 2751590Srgrimes printf("%s=%o", s, v); 2761590Srgrimes else 2771590Srgrimes printf("%s=%x", s, v); 2781590Srgrimes bits++; 2791590Srgrimes if (v && bits) { 2801590Srgrimes putchar('<'); 2811590Srgrimes while (i = *bits++) { 2821590Srgrimes if (v & (1 << (i-1))) { 2831590Srgrimes if (any) 2841590Srgrimes putchar(','); 2851590Srgrimes any = 1; 2861590Srgrimes for (; (c = *bits) > 32; bits++) 2871590Srgrimes putchar(c); 2881590Srgrimes } else 2891590Srgrimes for (; *bits > 32; bits++) 2901590Srgrimes ; 2911590Srgrimes } 2921590Srgrimes putchar('>'); 2931590Srgrimes } 2941590Srgrimes} 2951590Srgrimes 2961590Srgrimesvoid 2971590Srgrimesusage() 2981590Srgrimes{ 2991590Srgrimes (void)fprintf(stderr, "usage: mt [-f device] command [ count ]\n"); 3001590Srgrimes exit(1); 3011590Srgrimes} 3021590Srgrimes 3031590Srgrimes#if __STDC__ 3041590Srgrimes#include <stdarg.h> 3051590Srgrimes#else 3061590Srgrimes#include <varargs.h> 3071590Srgrimes#endif 3081590Srgrimes 3091590Srgrimesvoid 3101590Srgrimes#if __STDC__ 3111590Srgrimeserr(const char *fmt, ...) 3121590Srgrimes#else 3131590Srgrimeserr(fmt, va_alist) 3141590Srgrimes char *fmt; 3151590Srgrimes va_dcl 3161590Srgrimes#endif 3171590Srgrimes{ 3181590Srgrimes va_list ap; 3191590Srgrimes#if __STDC__ 3201590Srgrimes va_start(ap, fmt); 3211590Srgrimes#else 3221590Srgrimes va_start(ap); 3231590Srgrimes#endif 3241590Srgrimes (void)fprintf(stderr, "mt: "); 3251590Srgrimes (void)vfprintf(stderr, fmt, ap); 3261590Srgrimes va_end(ap); 3271590Srgrimes (void)fprintf(stderr, "\n"); 3281590Srgrimes exit(1); 3291590Srgrimes /* NOTREACHED */ 3301590Srgrimes} 3317913Sjoerg 3327913Sjoerg#if defined (__FreeBSD__) 3337913Sjoerg 3347913Sjoergstruct densities { 3357913Sjoerg int dens; 3367913Sjoerg const char *name; 3377913Sjoerg} dens [] = { 3387913Sjoerg { 0x1, "X3.22-1983 " }, 3397913Sjoerg { 0x2, "X3.39-1986 " }, 3407913Sjoerg { 0x3, "X3.54-1986 " }, 3417913Sjoerg { 0x5, "X3.136-1986 " }, 3427913Sjoerg { 0x6, "X3.157-1987 " }, 3437913Sjoerg { 0x7, "X3.116-1986 " }, 3447913Sjoerg { 0x8, "X3.158-1986 " }, 3457913Sjoerg { 0x9, "X3B5/87-099 " }, 3467913Sjoerg { 0xA, "X3B5/86-199 " }, 3477913Sjoerg { 0xB, "X3.56-1986 " }, 3487913Sjoerg { 0xC, "HI-TC1 " }, 3497913Sjoerg { 0xD, "HI-TC2 " }, 3507913Sjoerg { 0xF, "QIC-120 " }, 3517913Sjoerg { 0x10, "QIC-150 " }, 3527913Sjoerg { 0x11, "QIC-320 " }, 3537913Sjoerg { 0x12, "QIC-1350 " }, 3547913Sjoerg { 0x13, "X3B5/88-185A" }, 3557913Sjoerg { 0x14, "X3.202-1991 " }, 3567913Sjoerg { 0x15, "ECMA TC17 " }, 3577913Sjoerg { 0x16, "X3.193-1990 " }, 3587913Sjoerg { 0x17, "X3B5/91-174 " }, 3597913Sjoerg { 0, 0 } 3607913Sjoerg}; 3617913Sjoerg 3627913Sjoergconst char * 3637913Sjoerggetdens(int d) 3647913Sjoerg{ 3657913Sjoerg static char buf[20]; 3667913Sjoerg struct densities *sd; 3677913Sjoerg 3687913Sjoerg for (sd = dens; sd->dens; sd++) 3697913Sjoerg if (sd->dens == d) 3707913Sjoerg break; 3717913Sjoerg if (sd->dens == 0) { 3727913Sjoerg sprintf(buf, "0x%02x ", d); 3737913Sjoerg return buf; 3747913Sjoerg } 3757913Sjoerg else 3767913Sjoerg return sd->name; 3777913Sjoerg} 3787913Sjoerg 3797913Sjoergconst char * 3807913Sjoerggetblksiz(int bs) 3817913Sjoerg{ 3827913Sjoerg static char buf[25]; 3837913Sjoerg if (bs == 0) 3847913Sjoerg return "variable"; 3857913Sjoerg else { 3867913Sjoerg sprintf(buf, "= %d bytes", bs); 3877913Sjoerg return buf; 3887913Sjoerg } 3897913Sjoerg} 3907913Sjoerg 3917913Sjoerg 3927913Sjoergvoid 3937913Sjoergst_status(struct mtget *bp) 3947913Sjoerg{ 3957913Sjoerg printf("Present Mode: Density = %s Blocksize %s\n", 3967913Sjoerg getdens(bp->mt_density), getblksiz(bp->mt_blksiz)); 3977913Sjoerg printf("---------available modes---------\n"); 3987913Sjoerg printf("Mode 0: Density = %s Blocksize %s\n", 3997913Sjoerg getdens(bp->mt_density0), getblksiz(bp->mt_blksiz0)); 4007913Sjoerg printf("Mode 1: Density = %s Blocksize %s\n", 4017913Sjoerg getdens(bp->mt_density1), getblksiz(bp->mt_blksiz1)); 4027913Sjoerg printf("Mode 2: Density = %s Blocksize %s\n", 4037913Sjoerg getdens(bp->mt_density2), getblksiz(bp->mt_blksiz2)); 4047913Sjoerg printf("Mode 3: Density = %s Blocksize %s\n", 4057913Sjoerg getdens(bp->mt_density3), getblksiz(bp->mt_blksiz3)); 4067913Sjoerg} 4077913Sjoerg 4087913Sjoerg#endif /* defined (__FreeBSD__) */ 409