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 * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3127752Scharnierstatic const char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 341590Srgrimes#endif /* not lint */ 351590Srgrimes 361590Srgrimes#ifndef lint 3727752Scharnier#if 0 3823693Speterstatic char sccsid[] = "@(#)mt.c 8.2 (Berkeley) 5/4/95"; 3927752Scharnier#endif 401590Srgrimes#endif /* not lint */ 411590Srgrimes 4294505Scharnier#include <sys/cdefs.h> 4394505Scharnier__FBSDID("$FreeBSD$"); 4494505Scharnier 451590Srgrimes/* 461590Srgrimes * mt -- 471590Srgrimes * magnetic tape manipulation program 481590Srgrimes */ 491590Srgrimes#include <sys/types.h> 501590Srgrimes#include <sys/ioctl.h> 511590Srgrimes#include <sys/mtio.h> 5223693Speter 5323693Speter#include <ctype.h> 5427752Scharnier#include <err.h> 551590Srgrimes#include <fcntl.h> 5623693Speter#include <stdio.h> 571590Srgrimes#include <stdlib.h> 581590Srgrimes#include <string.h> 5923693Speter#include <unistd.h> 601590Srgrimes 617913Sjoerg/* the appropriate sections of <sys/mtio.h> are also #ifdef'd for FreeBSD */ 627913Sjoerg/* c_flags */ 637913Sjoerg#define NEED_2ARGS 0x01 647929Sjoerg#define ZERO_ALLOWED 0x02 657929Sjoerg#define IS_DENSITY 0x04 669541Sjoerg#define DISABLE_THIS 0x08 6739260Sgibbs#define IS_COMP 0x10 687913Sjoerg 6939260Sgibbs#ifndef TRUE 7039260Sgibbs#define TRUE 1 7139260Sgibbs#endif 7239260Sgibbs#ifndef FALSE 7339260Sgibbs#define FALSE 0 7439260Sgibbs#endif 7539260Sgibbs 761590Srgrimesstruct commands { 77152396Sdwmalone const char *c_name; 78229181Sdim unsigned long c_code; 791590Srgrimes int c_ronly; 807913Sjoerg int c_flags; 811590Srgrimes} com[] = { 8294505Scharnier { "bsf", MTBSF, 1, 0 }, 8394505Scharnier { "bsr", MTBSR, 1, 0 }, 849541Sjoerg /* XXX FreeBSD considered "eof" dangerous, since it's being 859541Sjoerg confused with "eom" (and is an alias for "weof" anyway) */ 869541Sjoerg { "eof", MTWEOF, 0, DISABLE_THIS }, 8794505Scharnier { "fsf", MTFSF, 1, 0 }, 8894505Scharnier { "fsr", MTFSR, 1, 0 }, 8994505Scharnier { "offline", MTOFFL, 1, 0 }, 9094505Scharnier { "rewind", MTREW, 1, 0 }, 9194505Scharnier { "rewoffl", MTOFFL, 1, 0 }, 9294505Scharnier { "status", MTNOP, 1, 0 }, 9341913Smjacob { "weof", MTWEOF, 0, ZERO_ALLOWED }, 9439260Sgibbs { "erase", MTERASE, 0, ZERO_ALLOWED}, 957913Sjoerg { "blocksize", MTSETBSIZ, 0, NEED_2ARGS|ZERO_ALLOWED }, 967929Sjoerg { "density", MTSETDNSTY, 0, NEED_2ARGS|ZERO_ALLOWED|IS_DENSITY }, 9794505Scharnier { "eom", MTEOD, 1, 0 }, 9894505Scharnier { "eod", MTEOD, 1, 0 }, 9994505Scharnier { "smk", MTWSS, 0, 0 }, 10094505Scharnier { "wss", MTWSS, 0, 0 }, 10194505Scharnier { "fss", MTFSS, 1, 0 }, 10294505Scharnier { "bss", MTBSS, 1, 0 }, 10339260Sgibbs { "comp", MTCOMP, 0, NEED_2ARGS|ZERO_ALLOWED|IS_COMP }, 10494505Scharnier { "retension", MTRETENS, 1, 0 }, 10594505Scharnier { "rdhpos", MTIOCRDHPOS, 0, 0 }, 10694505Scharnier { "rdspos", MTIOCRDSPOS, 0, 0 }, 10741913Smjacob { "sethpos", MTIOCHLOCATE, 0, NEED_2ARGS|ZERO_ALLOWED }, 10841913Smjacob { "setspos", MTIOCSLOCATE, 0, NEED_2ARGS|ZERO_ALLOWED }, 10994505Scharnier { "errstat", MTIOCERRSTAT, 0, 0 }, 11046928Smjacob { "setmodel", MTIOCSETEOTMODEL, 0, NEED_2ARGS|ZERO_ALLOWED }, 11146928Smjacob { "seteotmodel", MTIOCSETEOTMODEL, 0, NEED_2ARGS|ZERO_ALLOWED }, 11294505Scharnier { "getmodel", MTIOCGETEOTMODEL, 0, 0 }, 11394505Scharnier { "geteotmodel", MTIOCGETEOTMODEL, 0, 0 }, 11494505Scharnier { NULL, 0, 0, 0 } 1151590Srgrimes}; 1161590Srgrimes 11794505Scharnierconst char *getblksiz(int); 118152396Sdwmalonevoid printreg(const char *, u_int, const char *); 11992921Simpvoid status(struct mtget *); 12092921Simpvoid usage(void); 1217913Sjoergvoid st_status (struct mtget *); 1227929Sjoergint stringtodens (const char *s); 1237929Sjoergconst char *denstostring (int d); 12439260Sgibbsint denstobp(int d, int bpi); 12539260Sgibbsu_int32_t stringtocomp(const char *s); 126152396Sdwmaloneconst char *comptostring(u_int32_t comp); 12792921Simpvoid warn_eof(void); 1281590Srgrimes 1291590Srgrimesint 130152396Sdwmalonemain(int argc, char *argv[]) 1311590Srgrimes{ 132152396Sdwmalone struct commands *comp; 1331590Srgrimes struct mtget mt_status; 1341590Srgrimes struct mtop mt_com; 1351590Srgrimes int ch, len, mtfd; 136152396Sdwmalone const char *p, *tape; 1371590Srgrimes 1381590Srgrimes if ((tape = getenv("TAPE")) == NULL) 1391590Srgrimes tape = DEFTAPE; 1401590Srgrimes 14124360Simp while ((ch = getopt(argc, argv, "f:t:")) != -1) 1421590Srgrimes switch(ch) { 1431590Srgrimes case 'f': 1441590Srgrimes case 't': 1451590Srgrimes tape = optarg; 1461590Srgrimes break; 1471590Srgrimes case '?': 1481590Srgrimes default: 1491590Srgrimes usage(); 1501590Srgrimes } 1511590Srgrimes argc -= optind; 1521590Srgrimes argv += optind; 1531590Srgrimes 1541590Srgrimes if (argc < 1 || argc > 2) 1551590Srgrimes usage(); 1561590Srgrimes 1571590Srgrimes len = strlen(p = *argv++); 1581590Srgrimes for (comp = com;; comp++) { 1591590Srgrimes if (comp->c_name == NULL) 16027752Scharnier errx(1, "%s: unknown command", p); 1611590Srgrimes if (strncmp(p, comp->c_name, len) == 0) 1621590Srgrimes break; 1631590Srgrimes } 1647913Sjoerg if((comp->c_flags & NEED_2ARGS) && argc != 2) 1657913Sjoerg usage(); 1669541Sjoerg if(comp->c_flags & DISABLE_THIS) { 1679541Sjoerg warn_eof(); 1689541Sjoerg } 1691590Srgrimes if ((mtfd = open(tape, comp->c_ronly ? O_RDONLY : O_RDWR)) < 0) 17027752Scharnier err(1, "%s", tape); 1711590Srgrimes if (comp->c_code != MTNOP) { 1721590Srgrimes mt_com.mt_op = comp->c_code; 1731590Srgrimes if (*argv) { 1747929Sjoerg if (!isdigit(**argv) && 17541925Smjacob (comp->c_flags & IS_DENSITY)) { 1767929Sjoerg const char *dcanon; 1777929Sjoerg mt_com.mt_count = stringtodens(*argv); 1787929Sjoerg if (mt_com.mt_count == 0) 17927752Scharnier errx(1, "%s: unknown density", *argv); 1807929Sjoerg dcanon = denstostring(mt_com.mt_count); 1817929Sjoerg if (strcmp(dcanon, *argv) != 0) 1827929Sjoerg printf( 1837929Sjoerg "Using \"%s\" as an alias for %s\n", 1847929Sjoerg *argv, dcanon); 1857929Sjoerg p = ""; 18639260Sgibbs } else if (!isdigit(**argv) && 18741925Smjacob (comp->c_flags & IS_COMP)) { 18839260Sgibbs 18939260Sgibbs mt_com.mt_count = stringtocomp(*argv); 19039260Sgibbs if ((u_int32_t)mt_com.mt_count == 0xf0f0f0f0) 19139260Sgibbs errx(1, "%s: unknown compression", 19239260Sgibbs *argv); 19339260Sgibbs p = ""; 194152396Sdwmalone } else { 195152396Sdwmalone char *q; 1967929Sjoerg /* allow for hex numbers; useful for density */ 197152396Sdwmalone mt_com.mt_count = strtol(*argv, &q, 0); 198152396Sdwmalone p = q; 199152396Sdwmalone } 20041925Smjacob if ((mt_com.mt_count <= 2017913Sjoerg ((comp->c_flags & ZERO_ALLOWED)? -1: 0) 20239260Sgibbs && ((comp->c_flags & IS_COMP) == 0) 20341925Smjacob ) || *p) 20427752Scharnier errx(1, "%s: illegal count", *argv); 2051590Srgrimes } 2061590Srgrimes else 2071590Srgrimes mt_com.mt_count = 1; 20841913Smjacob switch (comp->c_code) { 20941945Smjacob case MTIOCERRSTAT: 21041945Smjacob { 21194505Scharnier unsigned int i; 21241945Smjacob union mterrstat umn; 21341945Smjacob struct scsi_tape_errors *s = &umn.scsi_errstat; 21441945Smjacob 21541945Smjacob if (ioctl(mtfd, comp->c_code, (caddr_t)&umn) < 0) 21641945Smjacob err(2, "%s", tape); 21741945Smjacob (void)printf("Last I/O Residual: %u\n", s->io_resid); 21842010Smjacob (void)printf(" Last I/O Command:"); 21942010Smjacob for (i = 0; i < sizeof (s->io_cdb); i++) 22042010Smjacob (void)printf(" %02X", s->io_cdb[i]); 22142010Smjacob (void)printf("\n"); 22241945Smjacob (void)printf(" Last I/O Sense:\n\n\t"); 22341945Smjacob for (i = 0; i < sizeof (s->io_sense); i++) { 22441945Smjacob (void)printf(" %02X", s->io_sense[i]); 22541945Smjacob if (((i + 1) & 0xf) == 0) { 22641945Smjacob (void)printf("\n\t"); 22741945Smjacob } 22841945Smjacob } 22941945Smjacob (void)printf("\n"); 23041945Smjacob (void)printf("Last Control Residual: %u\n", 23141945Smjacob s->ctl_resid); 23242010Smjacob (void)printf(" Last Control Command:"); 23342010Smjacob for (i = 0; i < sizeof (s->ctl_cdb); i++) 23442010Smjacob (void)printf(" %02X", s->ctl_cdb[i]); 23542010Smjacob (void)printf("\n"); 23641945Smjacob (void)printf(" Last Control Sense:\n\n\t"); 23741945Smjacob for (i = 0; i < sizeof (s->ctl_sense); i++) { 23841945Smjacob (void)printf(" %02X", s->ctl_sense[i]); 23941945Smjacob if (((i + 1) & 0xf) == 0) { 24041945Smjacob (void)printf("\n\t"); 24141945Smjacob } 24241945Smjacob } 24341945Smjacob (void)printf("\n\n"); 24441945Smjacob exit(0); 24541945Smjacob /* NOTREACHED */ 24641945Smjacob } 24741913Smjacob case MTIOCRDHPOS: 24841913Smjacob case MTIOCRDSPOS: 24941925Smjacob { 25041925Smjacob u_int32_t block; 25141925Smjacob if (ioctl(mtfd, comp->c_code, (caddr_t)&block) < 0) 25241913Smjacob err(2, "%s", tape); 25341945Smjacob (void)printf("%s: %s block location %u\n", tape, 25441913Smjacob (comp->c_code == MTIOCRDHPOS)? "hardware" : 25541925Smjacob "logical", block); 25641925Smjacob exit(0); 25741913Smjacob /* NOTREACHED */ 25841925Smjacob } 25941913Smjacob case MTIOCSLOCATE: 26041913Smjacob case MTIOCHLOCATE: 26141925Smjacob { 26241925Smjacob u_int32_t block = (u_int32_t)mt_com.mt_count; 26341925Smjacob if (ioctl(mtfd, comp->c_code, (caddr_t)&block) < 0) 26441913Smjacob err(2, "%s", tape); 26541925Smjacob exit(0); 26641913Smjacob /* NOTREACHED */ 26741925Smjacob } 26846928Smjacob case MTIOCGETEOTMODEL: 26946928Smjacob { 27046928Smjacob u_int32_t om; 27146928Smjacob if (ioctl(mtfd, MTIOCGETEOTMODEL, (caddr_t)&om) < 0) 27246928Smjacob err(2, "%s", tape); 27346928Smjacob (void)printf("%s: the model is %u filemar%s at EOT\n", 27446928Smjacob tape, om, (om > 1)? "ks" : "k"); 27546928Smjacob exit(0); 27646928Smjacob /* NOTREACHED */ 27746928Smjacob } 27846928Smjacob case MTIOCSETEOTMODEL: 27946928Smjacob { 28046928Smjacob u_int32_t om, nm = (u_int32_t)mt_com.mt_count; 28146928Smjacob if (ioctl(mtfd, MTIOCGETEOTMODEL, (caddr_t)&om) < 0) 28246928Smjacob err(2, "%s", tape); 28346928Smjacob if (ioctl(mtfd, comp->c_code, (caddr_t)&nm) < 0) 28446928Smjacob err(2, "%s", tape); 28546928Smjacob (void)printf("%s: old model was %u filemar%s at EOT\n", 28646928Smjacob tape, om, (om > 1)? "ks" : "k"); 28746928Smjacob (void)printf("%s: new model is %u filemar%s at EOT\n", 28846928Smjacob tape, nm, (nm > 1)? "ks" : "k"); 28946928Smjacob exit(0); 29046928Smjacob /* NOTREACHED */ 29146928Smjacob } 29241913Smjacob default: 29341913Smjacob break; 29441913Smjacob } 2951590Srgrimes if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) 29627752Scharnier err(1, "%s: %s", tape, comp->c_name); 2971590Srgrimes } else { 2981590Srgrimes if (ioctl(mtfd, MTIOCGET, &mt_status) < 0) 29927752Scharnier err(1, NULL); 3001590Srgrimes status(&mt_status); 3011590Srgrimes } 30241925Smjacob exit(0); 3031590Srgrimes /* NOTREACHED */ 3041590Srgrimes} 3051590Srgrimes 3061590Srgrimesstruct tape_desc { 3071590Srgrimes short t_type; /* type of magtape device */ 308152396Sdwmalone const char *t_name; /* printing name */ 309152396Sdwmalone const char *t_dsbits; /* "drive status" register */ 310152396Sdwmalone const char *t_erbits; /* "error" register */ 3111590Srgrimes} tapes[] = { 3127913Sjoerg { MT_ISAR, "SCSI tape drive", 0, 0 }, 31394505Scharnier { 0, NULL, 0, 0 } 3141590Srgrimes}; 3151590Srgrimes 3161590Srgrimes/* 3171590Srgrimes * Interpret the status buffer returned 3181590Srgrimes */ 3191590Srgrimesvoid 320152396Sdwmalonestatus(struct mtget *bp) 3211590Srgrimes{ 322152396Sdwmalone struct tape_desc *mt; 3231590Srgrimes 3241590Srgrimes for (mt = tapes;; mt++) { 3251590Srgrimes if (mt->t_type == 0) { 3261590Srgrimes (void)printf("%d: unknown tape drive type\n", 3271590Srgrimes bp->mt_type); 3281590Srgrimes return; 3291590Srgrimes } 3301590Srgrimes if (mt->t_type == bp->mt_type) 3311590Srgrimes break; 3321590Srgrimes } 3337913Sjoerg if(mt->t_type == MT_ISAR) 3347913Sjoerg st_status(bp); 3357913Sjoerg else { 33692764Sphk (void)printf("%s tape drive, residual=%d\n", 33792764Sphk mt->t_name, bp->mt_resid); 33892764Sphk printreg("ds", (unsigned short)bp->mt_dsreg, mt->t_dsbits); 33992764Sphk printreg("\ner", (unsigned short)bp->mt_erreg, mt->t_erbits); 34092764Sphk (void)putchar('\n'); 3417913Sjoerg } 3421590Srgrimes} 3431590Srgrimes 3441590Srgrimes/* 3451590Srgrimes * Print a register a la the %b format of the kernel's printf. 3461590Srgrimes */ 3471590Srgrimesvoid 348152396Sdwmaloneprintreg(const char *s, u_int v, const char *bits) 3491590Srgrimes{ 350152396Sdwmalone int i, any = 0; 351152396Sdwmalone char c; 3521590Srgrimes 3531590Srgrimes if (bits && *bits == 8) 3541590Srgrimes printf("%s=%o", s, v); 3551590Srgrimes else 3561590Srgrimes printf("%s=%x", s, v); 35711608Sbde if (!bits) 35811608Sbde return; 3591590Srgrimes bits++; 3601590Srgrimes if (v && bits) { 3611590Srgrimes putchar('<'); 36227752Scharnier while ((i = *bits++)) { 3631590Srgrimes if (v & (1 << (i-1))) { 3641590Srgrimes if (any) 3651590Srgrimes putchar(','); 3661590Srgrimes any = 1; 3671590Srgrimes for (; (c = *bits) > 32; bits++) 3681590Srgrimes putchar(c); 3691590Srgrimes } else 3701590Srgrimes for (; *bits > 32; bits++) 3711590Srgrimes ; 3721590Srgrimes } 3731590Srgrimes putchar('>'); 3741590Srgrimes } 3751590Srgrimes} 3761590Srgrimes 3771590Srgrimesvoid 378152396Sdwmaloneusage(void) 3791590Srgrimes{ 38094505Scharnier (void)fprintf(stderr, "usage: mt [-f device] command [count]\n"); 3811590Srgrimes exit(1); 3821590Srgrimes} 3831590Srgrimes 3847913Sjoergstruct densities { 3857913Sjoerg int dens; 38639260Sgibbs int bpmm; 38739260Sgibbs int bpi; 3887913Sjoerg const char *name; 38939260Sgibbs} dens[] = { 39039260Sgibbs /* 39139260Sgibbs * Taken from T10 Project 997D 39239260Sgibbs * SCSI-3 Stream Device Commands (SSC) 39339260Sgibbs * Revision 11, 4-Nov-97 39439260Sgibbs */ 39539260Sgibbs /*Num. bpmm bpi Reference */ 39639260Sgibbs { 0x1, 32, 800, "X3.22-1983" }, 39739260Sgibbs { 0x2, 63, 1600, "X3.39-1986" }, 39839260Sgibbs { 0x3, 246, 6250, "X3.54-1986" }, 39939260Sgibbs { 0x5, 315, 8000, "X3.136-1986" }, 40039260Sgibbs { 0x6, 126, 3200, "X3.157-1987" }, 40139260Sgibbs { 0x7, 252, 6400, "X3.116-1986" }, 40239260Sgibbs { 0x8, 315, 8000, "X3.158-1987" }, 40339260Sgibbs { 0x9, 491, 37871, "X3.180" }, 40439260Sgibbs { 0xA, 262, 6667, "X3B5/86-199" }, 40539260Sgibbs { 0xB, 63, 1600, "X3.56-1986" }, 40639260Sgibbs { 0xC, 500, 12690, "HI-TC1" }, 40739260Sgibbs { 0xD, 999, 25380, "HI-TC2" }, 40839260Sgibbs { 0xF, 394, 10000, "QIC-120" }, 40939260Sgibbs { 0x10, 394, 10000, "QIC-150" }, 41039260Sgibbs { 0x11, 630, 16000, "QIC-320" }, 41139260Sgibbs { 0x12, 2034, 51667, "QIC-1350" }, 41239260Sgibbs { 0x13, 2400, 61000, "X3B5/88-185A" }, 41339260Sgibbs { 0x14, 1703, 43245, "X3.202-1991" }, 41439260Sgibbs { 0x15, 1789, 45434, "ECMA TC17" }, 41539260Sgibbs { 0x16, 394, 10000, "X3.193-1990" }, 41639260Sgibbs { 0x17, 1673, 42500, "X3B5/91-174" }, 41739260Sgibbs { 0x18, 1673, 42500, "X3B5/92-50" }, 41899653Sjoerg { 0x19, 2460, 62500, "DLTapeIII" }, 41999653Sjoerg { 0x1A, 3214, 81633, "DLTapeIV(20GB)" }, 42099653Sjoerg { 0x1B, 3383, 85937, "DLTapeIV(35GB)" }, 42139260Sgibbs { 0x1C, 1654, 42000, "QIC-385M" }, 42239260Sgibbs { 0x1D, 1512, 38400, "QIC-410M" }, 42339260Sgibbs { 0x1E, 1385, 36000, "QIC-1000C" }, 42439260Sgibbs { 0x1F, 2666, 67733, "QIC-2100C" }, 42539260Sgibbs { 0x20, 2666, 67733, "QIC-6GB(M)" }, 42639260Sgibbs { 0x21, 2666, 67733, "QIC-20GB(C)" }, 42739260Sgibbs { 0x22, 1600, 40640, "QIC-2GB(C)" }, 42839260Sgibbs { 0x23, 2666, 67733, "QIC-875M" }, 42939260Sgibbs { 0x24, 2400, 61000, "DDS-2" }, 43039260Sgibbs { 0x25, 3816, 97000, "DDS-3" }, 43139260Sgibbs { 0x26, 3816, 97000, "DDS-4" }, 43239260Sgibbs { 0x27, 3056, 77611, "Mammoth" }, 43339260Sgibbs { 0x28, 1491, 37871, "X3.224" }, 43499653Sjoerg { 0x41, 3868, 98250, "DLTapeIV(40GB)" }, 435105155Sjoerg { 0x48, 5236, 133000, "SDLTapeI(110)" }, 436105155Sjoerg { 0x49, 7598, 193000, "SDLTapeI(160)" }, 43739260Sgibbs { 0, 0, 0, NULL } 4387913Sjoerg}; 4397913Sjoerg 44039260Sgibbsstruct compression_types { 44139260Sgibbs u_int32_t comp_number; 44239260Sgibbs const char *name; 44339260Sgibbs} comp_types[] = { 44439260Sgibbs { 0x00, "none" }, 44539260Sgibbs { 0x00, "off" }, 44639260Sgibbs { 0x10, "IDRC" }, 44739260Sgibbs { 0x20, "DCLZ" }, 44839260Sgibbs { 0xffffffff, "enable" }, 44939260Sgibbs { 0xffffffff, "on" }, 45039260Sgibbs { 0xf0f0f0f0, NULL} 45139260Sgibbs}; 45239260Sgibbs 4537913Sjoergconst char * 4547929Sjoergdenstostring(int d) 4557913Sjoerg{ 4567913Sjoerg static char buf[20]; 4577913Sjoerg struct densities *sd; 4587913Sjoerg 45944397Smjacob /* densities 0 and 0x7f are handled as special cases */ 46044397Smjacob if (d == 0) 46144397Smjacob return "default"; 46244397Smjacob if (d == 0x7f) 46344397Smjacob return "same"; 4647913Sjoerg for (sd = dens; sd->dens; sd++) 4657913Sjoerg if (sd->dens == d) 4667913Sjoerg break; 46744397Smjacob if (sd->dens == 0) 4687929Sjoerg sprintf(buf, "0x%02x", d); 46944397Smjacob else 47044397Smjacob sprintf(buf, "0x%02x:%s", d, sd->name); 47144397Smjacob return buf; 4727913Sjoerg} 4737913Sjoerg 47439260Sgibbs/* 47539260Sgibbs * Given a specific density number, return either the bits per inch or bits 47639260Sgibbs * per millimeter for the given density. 47739260Sgibbs */ 4787929Sjoergint 47939260Sgibbsdenstobp(int d, int bpi) 48039260Sgibbs{ 48139260Sgibbs struct densities *sd; 48239260Sgibbs 48339260Sgibbs for (sd = dens; sd->dens; sd++) 48439260Sgibbs if (sd->dens == d) 48539260Sgibbs break; 48639260Sgibbs if (sd->dens == 0) 48739260Sgibbs return(0); 48839260Sgibbs else { 48939260Sgibbs if (bpi) 49039260Sgibbs return(sd->bpi); 49139260Sgibbs else 49239260Sgibbs return(sd->bpmm); 49339260Sgibbs } 49439260Sgibbs} 49539260Sgibbs 49639260Sgibbsint 4977929Sjoergstringtodens(const char *s) 4987929Sjoerg{ 4997929Sjoerg struct densities *sd; 5007929Sjoerg size_t l = strlen(s); 5017929Sjoerg 5027929Sjoerg for (sd = dens; sd->dens; sd++) 5037929Sjoerg if (strncasecmp(sd->name, s, l) == 0) 5047929Sjoerg break; 5057929Sjoerg return sd->dens; 5067929Sjoerg} 5077929Sjoerg 5087929Sjoerg 5097913Sjoergconst char * 5107913Sjoerggetblksiz(int bs) 5117913Sjoerg{ 5127913Sjoerg static char buf[25]; 5137913Sjoerg if (bs == 0) 5147913Sjoerg return "variable"; 5157913Sjoerg else { 51639260Sgibbs sprintf(buf, "%d bytes", bs); 5177913Sjoerg return buf; 5187913Sjoerg } 5197913Sjoerg} 5207913Sjoerg 52139260Sgibbsconst char * 52239260Sgibbscomptostring(u_int32_t comp) 52339260Sgibbs{ 52439260Sgibbs static char buf[20]; 52539260Sgibbs struct compression_types *ct; 5267913Sjoerg 52739260Sgibbs if (comp == MT_COMP_DISABLED) 52839260Sgibbs return "disabled"; 52939260Sgibbs else if (comp == MT_COMP_UNSUPP) 53039260Sgibbs return "unsupported"; 53139260Sgibbs 53239260Sgibbs for (ct = comp_types; ct->name; ct++) 53339260Sgibbs if (ct->comp_number == comp) 53439260Sgibbs break; 53539260Sgibbs 53639260Sgibbs if (ct->comp_number == 0xf0f0f0f0) { 53744618Smjacob sprintf(buf, "0x%x", comp); 53839260Sgibbs return(buf); 53939260Sgibbs } else 54039260Sgibbs return(ct->name); 54139260Sgibbs} 54239260Sgibbs 54339260Sgibbsu_int32_t 54439260Sgibbsstringtocomp(const char *s) 54539260Sgibbs{ 54639260Sgibbs struct compression_types *ct; 54739260Sgibbs size_t l = strlen(s); 54839260Sgibbs 54939260Sgibbs for (ct = comp_types; ct->name; ct++) 55039260Sgibbs if (strncasecmp(ct->name, s, l) == 0) 55139260Sgibbs break; 55239260Sgibbs 55339260Sgibbs return(ct->comp_number); 55439260Sgibbs} 55539260Sgibbs 5567913Sjoergvoid 5577913Sjoergst_status(struct mtget *bp) 5587913Sjoerg{ 55944644Smjacob printf("Mode Density Blocksize bpi " 56039260Sgibbs "Compression\n" 56144644Smjacob "Current: %-17s %-12s %-7d %s\n" 56239260Sgibbs "---------available modes---------\n" 56344644Smjacob "0: %-17s %-12s %-7d %s\n" 56444644Smjacob "1: %-17s %-12s %-7d %s\n" 56544644Smjacob "2: %-17s %-12s %-7d %s\n" 56644644Smjacob "3: %-17s %-12s %-7d %s\n", 56739260Sgibbs denstostring(bp->mt_density), getblksiz(bp->mt_blksiz), 56839260Sgibbs denstobp(bp->mt_density, TRUE), comptostring(bp->mt_comp), 56939260Sgibbs denstostring(bp->mt_density0), getblksiz(bp->mt_blksiz0), 57039260Sgibbs denstobp(bp->mt_density0, TRUE), comptostring(bp->mt_comp0), 57139260Sgibbs denstostring(bp->mt_density1), getblksiz(bp->mt_blksiz1), 57239260Sgibbs denstobp(bp->mt_density1, TRUE), comptostring(bp->mt_comp1), 57339260Sgibbs denstostring(bp->mt_density2), getblksiz(bp->mt_blksiz2), 57439260Sgibbs denstobp(bp->mt_density2, TRUE), comptostring(bp->mt_comp2), 57539260Sgibbs denstostring(bp->mt_density3), getblksiz(bp->mt_blksiz3), 57639260Sgibbs denstobp(bp->mt_density3, TRUE), comptostring(bp->mt_comp3)); 57743629Smjacob 57843629Smjacob if (bp->mt_dsreg != MTIO_DSREG_NIL) { 57943629Smjacob auto char foo[32]; 58069248Skris const char sfmt[] = "Current Driver State: %s.\n"; 58143629Smjacob printf("---------------------------------\n"); 58243629Smjacob switch (bp->mt_dsreg) { 58343629Smjacob case MTIO_DSREG_REST: 58443629Smjacob printf(sfmt, "at rest"); 58543629Smjacob break; 58643629Smjacob case MTIO_DSREG_RBSY: 58743629Smjacob printf(sfmt, "Communicating with drive"); 58843629Smjacob break; 58943629Smjacob case MTIO_DSREG_WR: 59043629Smjacob printf(sfmt, "Writing"); 59143629Smjacob break; 59243629Smjacob case MTIO_DSREG_FMK: 59343629Smjacob printf(sfmt, "Writing Filemarks"); 59443629Smjacob break; 59543629Smjacob case MTIO_DSREG_ZER: 59643629Smjacob printf(sfmt, "Erasing"); 59743629Smjacob break; 59843629Smjacob case MTIO_DSREG_RD: 59943629Smjacob printf(sfmt, "Reading"); 60043629Smjacob break; 60143629Smjacob case MTIO_DSREG_FWD: 60243629Smjacob printf(sfmt, "Spacing Forward"); 60343629Smjacob break; 60443629Smjacob case MTIO_DSREG_REV: 60543629Smjacob printf(sfmt, "Spacing Reverse"); 60643629Smjacob break; 60743629Smjacob case MTIO_DSREG_POS: 60843629Smjacob printf(sfmt, 60943629Smjacob "Hardware Positioning (direction unknown)"); 61043629Smjacob break; 61143629Smjacob case MTIO_DSREG_REW: 61243629Smjacob printf(sfmt, "Rewinding"); 61343629Smjacob break; 61443629Smjacob case MTIO_DSREG_TEN: 61543629Smjacob printf(sfmt, "Retensioning"); 61643629Smjacob break; 61743629Smjacob case MTIO_DSREG_UNL: 61843629Smjacob printf(sfmt, "Unloading"); 61943629Smjacob break; 62043629Smjacob case MTIO_DSREG_LD: 62143629Smjacob printf(sfmt, "Loading"); 62243629Smjacob break; 62343629Smjacob default: 62443629Smjacob (void) sprintf(foo, "Unknown state 0x%x", bp->mt_dsreg); 62543629Smjacob printf(sfmt, foo); 62643629Smjacob break; 62743629Smjacob } 62843629Smjacob } 62971311Smjacob if (bp->mt_resid == 0 && bp->mt_fileno == (daddr_t) -1 && 63071311Smjacob bp->mt_blkno == (daddr_t) -1) 63143629Smjacob return; 63243629Smjacob printf("---------------------------------\n"); 63394505Scharnier printf("File Number: %d\tRecord Number: %d\tResidual Count %d\n", 63471311Smjacob bp->mt_fileno, bp->mt_blkno, bp->mt_resid); 6357913Sjoerg} 6367913Sjoerg 6379541Sjoergvoid 6389541Sjoergwarn_eof(void) 6399541Sjoerg{ 6409541Sjoerg fprintf(stderr, 6419541Sjoerg "The \"eof\" command has been disabled.\n" 6429541Sjoerg "Use \"weof\" if you really want to write end-of-file marks,\n" 6439541Sjoerg "or \"eom\" if you rather want to skip to the end of " 6449541Sjoerg "recorded medium.\n"); 6459541Sjoerg exit(1); 6469541Sjoerg} 647