xref: /titanic_54/usr/src/cmd/mt/mt.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate /*
7*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
8*7c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley Software License Agreement
9*7c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
10*7c478bd9Sstevel@tonic-gate  */
11*7c478bd9Sstevel@tonic-gate 
12*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
13*7c478bd9Sstevel@tonic-gate 
14*7c478bd9Sstevel@tonic-gate /*
15*7c478bd9Sstevel@tonic-gate  * mt -- magnetic tape manipulation program
16*7c478bd9Sstevel@tonic-gate  */
17*7c478bd9Sstevel@tonic-gate #include <stdio.h>
18*7c478bd9Sstevel@tonic-gate #include <ctype.h>
19*7c478bd9Sstevel@tonic-gate 
20*7c478bd9Sstevel@tonic-gate #include <errno.h>
21*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
22*7c478bd9Sstevel@tonic-gate #include <sys/mtio.h>
23*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
24*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
25*7c478bd9Sstevel@tonic-gate #include <sys/buf.h>
26*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
27*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
28*7c478bd9Sstevel@tonic-gate #include <sys/uio.h>
29*7c478bd9Sstevel@tonic-gate #include <string.h>
30*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
31*7c478bd9Sstevel@tonic-gate #include <unistd.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/scsi/targets/stdef.h>
34*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #define	equal(s1, s2)	(strcmp(s1, s2) == 0)
38*7c478bd9Sstevel@tonic-gate #define	MTASF		100	/* absolute file positioning; first file is 0 */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate /*
41*7c478bd9Sstevel@tonic-gate  * This can't be DEFTAPE in mtio.h because that is currently the rewinding
42*7c478bd9Sstevel@tonic-gate  * unit which makes 'mt fsf' a questionable activity at best.
43*7c478bd9Sstevel@tonic-gate  */
44*7c478bd9Sstevel@tonic-gate #define	DEFAULT_NRW_TAPE	"/dev/rmt/0n"
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate static int mtfd;
47*7c478bd9Sstevel@tonic-gate static struct mtop mt_com;
48*7c478bd9Sstevel@tonic-gate static struct mtget mt_status;
49*7c478bd9Sstevel@tonic-gate static void print_config(void);
50*7c478bd9Sstevel@tonic-gate static char *print_key(short key_code);
51*7c478bd9Sstevel@tonic-gate static void printreg(char *, ushort_t, char *);
52*7c478bd9Sstevel@tonic-gate static void status(struct mtget *);
53*7c478bd9Sstevel@tonic-gate static char *tape;
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate /* Pseudo flag for open even if drive is not ready (Unloaded) or reserved */
56*7c478bd9Sstevel@tonic-gate #define	O_UNLOAD (O_RDWR | O_NDELAY)
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate static struct commands {
59*7c478bd9Sstevel@tonic-gate 	char *c_name;
60*7c478bd9Sstevel@tonic-gate 	int c_code;
61*7c478bd9Sstevel@tonic-gate 	int c_oflag;
62*7c478bd9Sstevel@tonic-gate 	int c_usecnt;
63*7c478bd9Sstevel@tonic-gate } com[] = {
64*7c478bd9Sstevel@tonic-gate 	{ "weof",		MTWEOF,			O_RDWR,		1 },
65*7c478bd9Sstevel@tonic-gate 	{ "eof",		MTWEOF,			O_RDWR,		1 },
66*7c478bd9Sstevel@tonic-gate 	{ "fsf",		MTFSF,			O_RDONLY,	1 },
67*7c478bd9Sstevel@tonic-gate 	{ "bsf",		MTBSF,			O_RDONLY,	1 },
68*7c478bd9Sstevel@tonic-gate 	{ "asf",		MTASF,			O_RDONLY,	1 },
69*7c478bd9Sstevel@tonic-gate 	{ "fsr",		MTFSR,			O_RDONLY,	1 },
70*7c478bd9Sstevel@tonic-gate 	{ "bsr",		MTBSR,			O_RDONLY,	1 },
71*7c478bd9Sstevel@tonic-gate 	{ "rewind",		MTREW,			O_RDONLY,	0 },
72*7c478bd9Sstevel@tonic-gate 	{ "offline",		MTOFFL,			O_RDONLY,	0 },
73*7c478bd9Sstevel@tonic-gate 	{ "rewoffl",		MTOFFL,			O_RDONLY,	0 },
74*7c478bd9Sstevel@tonic-gate 	{ "status",		MTNOP,			O_RDONLY,	0 },
75*7c478bd9Sstevel@tonic-gate 	{ "retension",		MTRETEN,		O_RDONLY,	0 },
76*7c478bd9Sstevel@tonic-gate 	{ "erase",		MTERASE,		O_RDWR,		0 },
77*7c478bd9Sstevel@tonic-gate 	{ "eom",		MTEOM,			O_RDONLY,	0 },
78*7c478bd9Sstevel@tonic-gate 	{ "nbsf",		MTNBSF,			O_RDONLY,	1 },
79*7c478bd9Sstevel@tonic-gate 	{ "reserve",		MTIOCRESERVE,		O_RDONLY,	0 },
80*7c478bd9Sstevel@tonic-gate 	{ "release",		MTIOCRELEASE,		O_RDONLY,	0 },
81*7c478bd9Sstevel@tonic-gate 	{ "forcereserve",	MTIOCFORCERESERVE,	O_UNLOAD,	0 },
82*7c478bd9Sstevel@tonic-gate 	{ "config",		MTIOCGETDRIVETYPE,	O_UNLOAD,	0 },
83*7c478bd9Sstevel@tonic-gate 	{ 0 }
84*7c478bd9Sstevel@tonic-gate };
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate #ifdef sun
87*7c478bd9Sstevel@tonic-gate static struct mt_tape_info tapes[] = MT_TAPE_INFO;
88*7c478bd9Sstevel@tonic-gate #endif /* sun */
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
91*7c478bd9Sstevel@tonic-gate {
92*7c478bd9Sstevel@tonic-gate 	register char *cp;
93*7c478bd9Sstevel@tonic-gate 	register struct commands *comp;
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate 	if (argc > 2 && (equal(argv[1], "-t") || equal(argv[1], "-f"))) {
96*7c478bd9Sstevel@tonic-gate 		argc -= 2;
97*7c478bd9Sstevel@tonic-gate 		tape = argv[2];
98*7c478bd9Sstevel@tonic-gate 		argv += 2;
99*7c478bd9Sstevel@tonic-gate 	} else
100*7c478bd9Sstevel@tonic-gate 		if ((tape = getenv("TAPE")) == NULL)
101*7c478bd9Sstevel@tonic-gate 			tape = DEFAULT_NRW_TAPE;
102*7c478bd9Sstevel@tonic-gate 	if (argc < 2) {
103*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
104*7c478bd9Sstevel@tonic-gate 		    "usage: mt [ -f device ] command [ count ]\n");
105*7c478bd9Sstevel@tonic-gate 		exit(1);
106*7c478bd9Sstevel@tonic-gate 	}
107*7c478bd9Sstevel@tonic-gate 	cp = argv[1];
108*7c478bd9Sstevel@tonic-gate 	for (comp = com; comp->c_name != NULL; comp++)
109*7c478bd9Sstevel@tonic-gate 		if (strncmp(cp, comp->c_name, strlen(cp)) == 0)
110*7c478bd9Sstevel@tonic-gate 			break;
111*7c478bd9Sstevel@tonic-gate 	if (comp->c_name == NULL) {
112*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "mt: unknown command: %s\n", cp);
113*7c478bd9Sstevel@tonic-gate 		exit(1);
114*7c478bd9Sstevel@tonic-gate 	}
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	if ((mtfd = open(tape, comp->c_oflag)) < 0) {
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 		/*
119*7c478bd9Sstevel@tonic-gate 		 * Provide additional error message decoding since
120*7c478bd9Sstevel@tonic-gate 		 * we need additional error codes to fix them problem.
121*7c478bd9Sstevel@tonic-gate 		 */
122*7c478bd9Sstevel@tonic-gate 		if (errno == EIO) {
123*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
124*7c478bd9Sstevel@tonic-gate 			    "%s: no tape loaded or drive offline\n",
125*7c478bd9Sstevel@tonic-gate 				tape);
126*7c478bd9Sstevel@tonic-gate 		} else if (errno == EACCES) {
127*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
128*7c478bd9Sstevel@tonic-gate 				"%s: write protected or reserved.\n", tape);
129*7c478bd9Sstevel@tonic-gate 		} else {
130*7c478bd9Sstevel@tonic-gate 			perror(tape);
131*7c478bd9Sstevel@tonic-gate 		}
132*7c478bd9Sstevel@tonic-gate 		exit(1);
133*7c478bd9Sstevel@tonic-gate 	}
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 	if (comp->c_code == MTIOCFORCERESERVE ||
136*7c478bd9Sstevel@tonic-gate 			comp->c_code == MTIOCRESERVE ||
137*7c478bd9Sstevel@tonic-gate 				comp->c_code == MTIOCRELEASE)  {
138*7c478bd9Sstevel@tonic-gate 		/*
139*7c478bd9Sstevel@tonic-gate 		 * Handle all MTIOC ioctls used in
140*7c478bd9Sstevel@tonic-gate 		 * reservation/release/takeownership.
141*7c478bd9Sstevel@tonic-gate 		 */
142*7c478bd9Sstevel@tonic-gate 		if (ioctl(mtfd, comp->c_code) < 0) {
143*7c478bd9Sstevel@tonic-gate 			perror("mt");
144*7c478bd9Sstevel@tonic-gate 			exit(2);
145*7c478bd9Sstevel@tonic-gate 		}
146*7c478bd9Sstevel@tonic-gate 	} else if (comp->c_code == MTASF) {
147*7c478bd9Sstevel@tonic-gate 		/*
148*7c478bd9Sstevel@tonic-gate 		 * Handle absolute file positioning.  Ask tape driver
149*7c478bd9Sstevel@tonic-gate 		 * where tape is and then skip to desired file.  If
150*7c478bd9Sstevel@tonic-gate 		 * driver doesn't support get location ioctl, rewind
151*7c478bd9Sstevel@tonic-gate 		 * the tape and then space to the desired file.
152*7c478bd9Sstevel@tonic-gate 		 */
153*7c478bd9Sstevel@tonic-gate 		int usecnt;
154*7c478bd9Sstevel@tonic-gate 		int mt_fileno;
155*7c478bd9Sstevel@tonic-gate 		struct mtget mt_status;
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 		usecnt = argc > 2 && comp->c_usecnt;
158*7c478bd9Sstevel@tonic-gate 		mt_fileno = usecnt ? atoi(argv[2]) : 1;
159*7c478bd9Sstevel@tonic-gate 		if (mt_fileno < 0) {
160*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "mt: negative file number\n");
161*7c478bd9Sstevel@tonic-gate 			exit(1);
162*7c478bd9Sstevel@tonic-gate 		}
163*7c478bd9Sstevel@tonic-gate 		(void) ioctl(mtfd, MTIOCGET, (char *)&mt_status);
164*7c478bd9Sstevel@tonic-gate 		if (ioctl(mtfd, MTIOCGET, (char *)&mt_status) < 0) {
165*7c478bd9Sstevel@tonic-gate 			perror("mt");
166*7c478bd9Sstevel@tonic-gate 			exit(2);
167*7c478bd9Sstevel@tonic-gate 		}
168*7c478bd9Sstevel@tonic-gate 		/*
169*7c478bd9Sstevel@tonic-gate 		 * Check if device supports reporting current file
170*7c478bd9Sstevel@tonic-gate 		 * tape file position.  If not, rewind the tape, and
171*7c478bd9Sstevel@tonic-gate 		 * space forward.
172*7c478bd9Sstevel@tonic-gate 		 */
173*7c478bd9Sstevel@tonic-gate 		if (!(mt_status.mt_flags & MTF_ASF)) {
174*7c478bd9Sstevel@tonic-gate 			/* printf("mt: rewind\n"); */
175*7c478bd9Sstevel@tonic-gate 			mt_status.mt_fileno = 0;
176*7c478bd9Sstevel@tonic-gate 			mt_com.mt_count = 1;
177*7c478bd9Sstevel@tonic-gate 			mt_com.mt_op = MTREW;
178*7c478bd9Sstevel@tonic-gate 			if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) {
179*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "%s %s %d ",
180*7c478bd9Sstevel@tonic-gate 					tape, comp->c_name, mt_fileno);
181*7c478bd9Sstevel@tonic-gate 				perror("mt");
182*7c478bd9Sstevel@tonic-gate 				exit(2);
183*7c478bd9Sstevel@tonic-gate 			}
184*7c478bd9Sstevel@tonic-gate 		}
185*7c478bd9Sstevel@tonic-gate 		if (mt_fileno < mt_status.mt_fileno) {
186*7c478bd9Sstevel@tonic-gate 			mt_com.mt_op = MTNBSF;
187*7c478bd9Sstevel@tonic-gate 			mt_com.mt_count =  mt_status.mt_fileno - mt_fileno;
188*7c478bd9Sstevel@tonic-gate 			/* printf("mt: bsf= %d\n", mt_com.mt_count); */
189*7c478bd9Sstevel@tonic-gate 		} else {
190*7c478bd9Sstevel@tonic-gate 			mt_com.mt_op = MTFSF;
191*7c478bd9Sstevel@tonic-gate 			mt_com.mt_count =  mt_fileno - mt_status.mt_fileno;
192*7c478bd9Sstevel@tonic-gate 			/* printf("mt: fsf= %d\n", mt_com.mt_count); */
193*7c478bd9Sstevel@tonic-gate 		}
194*7c478bd9Sstevel@tonic-gate 		if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) {
195*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s %s %d ", tape, comp->c_name,
196*7c478bd9Sstevel@tonic-gate 				mt_fileno);
197*7c478bd9Sstevel@tonic-gate 			perror("failed");
198*7c478bd9Sstevel@tonic-gate 			exit(2);
199*7c478bd9Sstevel@tonic-gate 		}
200*7c478bd9Sstevel@tonic-gate 	} else if (comp->c_code == MTIOCGETDRIVETYPE) {
201*7c478bd9Sstevel@tonic-gate 		print_config();
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 	/* Handle regular mag tape ioctls */
204*7c478bd9Sstevel@tonic-gate 	} else if (comp->c_code != MTNOP) {
205*7c478bd9Sstevel@tonic-gate 		int usecnt;
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 		mt_com.mt_op = comp->c_code;
208*7c478bd9Sstevel@tonic-gate 		usecnt = argc > 2 && comp->c_usecnt;
209*7c478bd9Sstevel@tonic-gate 		mt_com.mt_count = (usecnt ? atoi(argv[2]) : 1);
210*7c478bd9Sstevel@tonic-gate 		if (mt_com.mt_count < 0) {
211*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "mt: negative repeat count\n");
212*7c478bd9Sstevel@tonic-gate 			exit(1);
213*7c478bd9Sstevel@tonic-gate 		}
214*7c478bd9Sstevel@tonic-gate 		if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) {
215*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s %s %ld ", tape, comp->c_name,
216*7c478bd9Sstevel@tonic-gate 				mt_com.mt_count);
217*7c478bd9Sstevel@tonic-gate 			perror("failed");
218*7c478bd9Sstevel@tonic-gate 			exit(2);
219*7c478bd9Sstevel@tonic-gate 		}
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate 	/* Handle status ioctl */
222*7c478bd9Sstevel@tonic-gate 	} else {
223*7c478bd9Sstevel@tonic-gate 		if (ioctl(mtfd, MTIOCGET, (char *)&mt_status) < 0) {
224*7c478bd9Sstevel@tonic-gate 			perror("mt");
225*7c478bd9Sstevel@tonic-gate 			exit(2);
226*7c478bd9Sstevel@tonic-gate 		}
227*7c478bd9Sstevel@tonic-gate 		status(&mt_status);
228*7c478bd9Sstevel@tonic-gate 	}
229*7c478bd9Sstevel@tonic-gate 	return (0);
230*7c478bd9Sstevel@tonic-gate }
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate static void
233*7c478bd9Sstevel@tonic-gate print_config(void)
234*7c478bd9Sstevel@tonic-gate {
235*7c478bd9Sstevel@tonic-gate 	struct mtdrivetype mdt;
236*7c478bd9Sstevel@tonic-gate 	struct mtdrivetype_request mdt_req;
237*7c478bd9Sstevel@tonic-gate 	char cfgname[48];
238*7c478bd9Sstevel@tonic-gate 	char tmp[2];
239*7c478bd9Sstevel@tonic-gate 	char *name;
240*7c478bd9Sstevel@tonic-gate 	int i;
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	mdt_req.size = sizeof (mdt);
243*7c478bd9Sstevel@tonic-gate 	mdt_req.mtdtp = &mdt;
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	if (ioctl(mtfd, MTIOCGETDRIVETYPE, &mdt_req) != 0) {
246*7c478bd9Sstevel@tonic-gate 		perror("mt config");
247*7c478bd9Sstevel@tonic-gate 		return;
248*7c478bd9Sstevel@tonic-gate 	}
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	/*
251*7c478bd9Sstevel@tonic-gate 	 * remove trailing spaces from product id.
252*7c478bd9Sstevel@tonic-gate 	 */
253*7c478bd9Sstevel@tonic-gate 	for (i = VIDPIDLEN; i; i--) {
254*7c478bd9Sstevel@tonic-gate 		if (isspace(mdt.vid[i]) || mdt.vid[i] == '*') {
255*7c478bd9Sstevel@tonic-gate 			mdt.vid[i] = 0;
256*7c478bd9Sstevel@tonic-gate 		} else if (mdt.vid[i] == 0) {
257*7c478bd9Sstevel@tonic-gate 			continue;
258*7c478bd9Sstevel@tonic-gate 		} else {
259*7c478bd9Sstevel@tonic-gate 			break;
260*7c478bd9Sstevel@tonic-gate 		}
261*7c478bd9Sstevel@tonic-gate 	}
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	/*
264*7c478bd9Sstevel@tonic-gate 	 * If this is a generic name display the Vid and Pid instead.
265*7c478bd9Sstevel@tonic-gate 	 */
266*7c478bd9Sstevel@tonic-gate 	if (strstr(mdt.name, "Vendor '") == NULL) {
267*7c478bd9Sstevel@tonic-gate 		name = mdt.name;
268*7c478bd9Sstevel@tonic-gate 	} else {
269*7c478bd9Sstevel@tonic-gate 		name = mdt.vid;
270*7c478bd9Sstevel@tonic-gate 	}
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	/*
273*7c478bd9Sstevel@tonic-gate 	 * Attempt to create a configuration name using vid and pid.
274*7c478bd9Sstevel@tonic-gate 	 */
275*7c478bd9Sstevel@tonic-gate 	(void) strcpy(cfgname, "CFG");
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	for (tmp[1] = i = 0; i < VIDPIDLEN; i++) {
278*7c478bd9Sstevel@tonic-gate 		if (!isalnum(name[i]))
279*7c478bd9Sstevel@tonic-gate 			continue;
280*7c478bd9Sstevel@tonic-gate 		if (isspace(name[i]))
281*7c478bd9Sstevel@tonic-gate 			continue;
282*7c478bd9Sstevel@tonic-gate 		tmp[0] = toupper(name[i]);
283*7c478bd9Sstevel@tonic-gate 		(void) strncat(cfgname, tmp, 1);
284*7c478bd9Sstevel@tonic-gate 	}
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	(void) printf("\"%s\", \"%s\", \"%s\";\n", mdt.vid, name, cfgname);
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	/*
289*7c478bd9Sstevel@tonic-gate 	 * Don't want show some bits, ST_DYNAMIC is set in the driver
290*7c478bd9Sstevel@tonic-gate 	 * so one can tell that its not a compiled in config.
291*7c478bd9Sstevel@tonic-gate 	 * The ST_LONG_ERASE and ST_LONG_TIMEOUTS are not displayed
292*7c478bd9Sstevel@tonic-gate 	 * becouse the timeout values below already reflect them being
293*7c478bd9Sstevel@tonic-gate 	 * set.
294*7c478bd9Sstevel@tonic-gate 	 * Also ST_KNOWS_MEDIA is not displayed as it can not be configured
295*7c478bd9Sstevel@tonic-gate 	 * from an st.conf entry.
296*7c478bd9Sstevel@tonic-gate 	 */
297*7c478bd9Sstevel@tonic-gate 	(void) printf("%s = 2,0x%X,%d,0x%X,", cfgname,
298*7c478bd9Sstevel@tonic-gate 	    mdt.type, mdt.bsize, mdt.options &
299*7c478bd9Sstevel@tonic-gate 	    ~(ST_DYNAMIC | ST_LONG_ERASE | ST_LONG_TIMEOUTS | ST_KNOWS_MEDIA));
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate 	(void) printf("4,0x%2.2X,0x%2.2X,0x%2.2X,0x%2.2X,%d,",
302*7c478bd9Sstevel@tonic-gate 	    mdt.densities[0], mdt.densities[1], mdt.densities[2],
303*7c478bd9Sstevel@tonic-gate 	    mdt.densities[3], mdt.default_density >> 3);
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 	(void) printf("%d,%d,%d,%d,%d,%d,%d;\n", mdt.non_motion_timeout,
306*7c478bd9Sstevel@tonic-gate 	    mdt.io_timeout, mdt.rewind_timeout, mdt.space_timeout,
307*7c478bd9Sstevel@tonic-gate 	    mdt.load_timeout, mdt.unload_timeout, mdt.erase_timeout);
308*7c478bd9Sstevel@tonic-gate }
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate /*
311*7c478bd9Sstevel@tonic-gate  * Interpret the status buffer returned
312*7c478bd9Sstevel@tonic-gate  */
313*7c478bd9Sstevel@tonic-gate static void
314*7c478bd9Sstevel@tonic-gate status(bp)
315*7c478bd9Sstevel@tonic-gate 	register struct mtget *bp;
316*7c478bd9Sstevel@tonic-gate {
317*7c478bd9Sstevel@tonic-gate 	register struct mt_tape_info *mt = NULL;
318*7c478bd9Sstevel@tonic-gate 	struct mtdrivetype mdt;
319*7c478bd9Sstevel@tonic-gate 	struct mtdrivetype_request mdt_req;
320*7c478bd9Sstevel@tonic-gate 	char *name = (char *)NULL;
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	/*
323*7c478bd9Sstevel@tonic-gate 	 * Make a call to MTIOCGETDRIVETYPE ioctl, Also use old method
324*7c478bd9Sstevel@tonic-gate 	 * of MT_TAPE_INFO for now, but MT_TAPE_INFO should dissapear in 2.7
325*7c478bd9Sstevel@tonic-gate 	 */
326*7c478bd9Sstevel@tonic-gate 	mdt_req.size = sizeof (struct mtdrivetype);
327*7c478bd9Sstevel@tonic-gate 	mdt_req.mtdtp = &mdt;
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate 	if (ioctl(mtfd, MTIOCGETDRIVETYPE, &mdt_req) == 0) {
330*7c478bd9Sstevel@tonic-gate 		name = mdt.name;
331*7c478bd9Sstevel@tonic-gate 		if (strstr(mdt.name, "Vendor '") != NULL) {
332*7c478bd9Sstevel@tonic-gate 			(void) printf("Unconfigured Drive: ");
333*7c478bd9Sstevel@tonic-gate 		}
334*7c478bd9Sstevel@tonic-gate 	} else {
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 		for (mt = tapes; mt->t_type; mt++) {
337*7c478bd9Sstevel@tonic-gate 			if (mt->t_type == bp->mt_type) {
338*7c478bd9Sstevel@tonic-gate 				break;
339*7c478bd9Sstevel@tonic-gate 			}
340*7c478bd9Sstevel@tonic-gate 		}
341*7c478bd9Sstevel@tonic-gate 	}
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 	/* Handle SCSI tape drives specially. */
344*7c478bd9Sstevel@tonic-gate 	if ((bp->mt_flags & MTF_SCSI)) {
345*7c478bd9Sstevel@tonic-gate 		if (name == (char *)NULL) {
346*7c478bd9Sstevel@tonic-gate 			if (mt->t_type == 0)
347*7c478bd9Sstevel@tonic-gate 				name = "SCSI";
348*7c478bd9Sstevel@tonic-gate 			else
349*7c478bd9Sstevel@tonic-gate 				name = mt->t_name;
350*7c478bd9Sstevel@tonic-gate 		}
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 		(void) printf("%s tape drive:\n", name);
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 		(void) printf("   sense key(0x%x)= %s   residual= %ld   ",
356*7c478bd9Sstevel@tonic-gate 			bp->mt_erreg, print_key(bp->mt_erreg), bp->mt_resid);
357*7c478bd9Sstevel@tonic-gate 		(void) printf("retries= %d\n", bp->mt_dsreg);
358*7c478bd9Sstevel@tonic-gate 		(void) printf("   file no= %ld   block no= %ld\n",
359*7c478bd9Sstevel@tonic-gate 			bp->mt_fileno, bp->mt_blkno);
360*7c478bd9Sstevel@tonic-gate 	} else {
361*7c478bd9Sstevel@tonic-gate 		/* Handle non-SCSI drives here. */
362*7c478bd9Sstevel@tonic-gate 		if (mt->t_type == 0) {
363*7c478bd9Sstevel@tonic-gate 			(void) printf("unknown tape drive type (0x%x)\n",
364*7c478bd9Sstevel@tonic-gate 			    bp->mt_type);
365*7c478bd9Sstevel@tonic-gate 			return;
366*7c478bd9Sstevel@tonic-gate 		}
367*7c478bd9Sstevel@tonic-gate 		(void) printf("%s tape drive:\n   residual= %ld", mt->t_name,
368*7c478bd9Sstevel@tonic-gate 		    bp->mt_resid);
369*7c478bd9Sstevel@tonic-gate 		printreg("   ds", (ushort_t)bp->mt_dsreg, mt->t_dsbits);
370*7c478bd9Sstevel@tonic-gate 		printreg("   er", (ushort_t)bp->mt_erreg, mt->t_erbits);
371*7c478bd9Sstevel@tonic-gate 		(void) putchar('\n');
372*7c478bd9Sstevel@tonic-gate 	}
373*7c478bd9Sstevel@tonic-gate }
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate #ifdef	sun
377*7c478bd9Sstevel@tonic-gate /*
378*7c478bd9Sstevel@tonic-gate  * Define SCSI sense key error messages.
379*7c478bd9Sstevel@tonic-gate  *
380*7c478bd9Sstevel@tonic-gate  * The first 16 sense keys are SCSI standard
381*7c478bd9Sstevel@tonic-gate  * sense keys. The keys after this are
382*7c478bd9Sstevel@tonic-gate  * Sun Specifice 'sense' keys- e.g., crap.
383*7c478bd9Sstevel@tonic-gate  */
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate static char *standard_sense_keys[16] = {
386*7c478bd9Sstevel@tonic-gate 	"No Additional Sense",		/* 0x00 */
387*7c478bd9Sstevel@tonic-gate 	"Soft Error",			/* 0x01 */
388*7c478bd9Sstevel@tonic-gate 	"Not Ready",			/* 0x02 */
389*7c478bd9Sstevel@tonic-gate 	"Media Error",			/* 0x03 */
390*7c478bd9Sstevel@tonic-gate 	"Hardware Error",		/* 0x04 */
391*7c478bd9Sstevel@tonic-gate 	"Illegal Request",		/* 0x05 */
392*7c478bd9Sstevel@tonic-gate 	"Unit Attention",		/* 0x06 */
393*7c478bd9Sstevel@tonic-gate 	"Write Protected",		/* 0x07 */
394*7c478bd9Sstevel@tonic-gate 	"Blank Check",			/* 0x08 */
395*7c478bd9Sstevel@tonic-gate 	"Vendor Unique",		/* 0x09 */
396*7c478bd9Sstevel@tonic-gate 	"Copy Aborted",			/* 0x0a */
397*7c478bd9Sstevel@tonic-gate 	"Aborted Command",		/* 0x0b */
398*7c478bd9Sstevel@tonic-gate 	"Equal Error",			/* 0x0c */
399*7c478bd9Sstevel@tonic-gate 	"Volume Overflow",		/* 0x0d */
400*7c478bd9Sstevel@tonic-gate 	"Miscompare Error",		/* 0x0e */
401*7c478bd9Sstevel@tonic-gate 	"Reserved"			/* 0x0f */
402*7c478bd9Sstevel@tonic-gate };
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate static char *sun_sense_keys[] = {
405*7c478bd9Sstevel@tonic-gate 	"fatal",			/* 0x10 */
406*7c478bd9Sstevel@tonic-gate 	"timeout",			/* 0x11 */
407*7c478bd9Sstevel@tonic-gate 	"EOF",				/* 0x12 */
408*7c478bd9Sstevel@tonic-gate 	"EOT",				/* 0x13 */
409*7c478bd9Sstevel@tonic-gate 	"length error",			/* 0x14 */
410*7c478bd9Sstevel@tonic-gate 	"BOT",				/* 0x15 */
411*7c478bd9Sstevel@tonic-gate 	"wrong tape media",		/* 0x16 */
412*7c478bd9Sstevel@tonic-gate 	0
413*7c478bd9Sstevel@tonic-gate };
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate /*
416*7c478bd9Sstevel@tonic-gate  * Return the text string associated with the sense key value.
417*7c478bd9Sstevel@tonic-gate  */
418*7c478bd9Sstevel@tonic-gate static char *
419*7c478bd9Sstevel@tonic-gate print_key(short key_code)
420*7c478bd9Sstevel@tonic-gate {
421*7c478bd9Sstevel@tonic-gate 	static char unknown[32];
422*7c478bd9Sstevel@tonic-gate 	short i;
423*7c478bd9Sstevel@tonic-gate 	if (key_code >= 0 && key_code <= 0x10) {
424*7c478bd9Sstevel@tonic-gate 		return (standard_sense_keys[key_code]);
425*7c478bd9Sstevel@tonic-gate 	}
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 	i = 0;
428*7c478bd9Sstevel@tonic-gate 	while (sun_sense_keys[i]) {
429*7c478bd9Sstevel@tonic-gate 		if ((i + 0x10) == key_code) {
430*7c478bd9Sstevel@tonic-gate 			return (sun_sense_keys[i]);
431*7c478bd9Sstevel@tonic-gate 		} else i++;
432*7c478bd9Sstevel@tonic-gate 	}
433*7c478bd9Sstevel@tonic-gate 	(void) sprintf(unknown, "unknown sense key: 0x%x",
434*7c478bd9Sstevel@tonic-gate 	    (unsigned int) key_code);
435*7c478bd9Sstevel@tonic-gate 	return (unknown);
436*7c478bd9Sstevel@tonic-gate }
437*7c478bd9Sstevel@tonic-gate #endif
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate /*
441*7c478bd9Sstevel@tonic-gate  * Print a register a la the %b format of the kernel's printf
442*7c478bd9Sstevel@tonic-gate  */
443*7c478bd9Sstevel@tonic-gate static void
444*7c478bd9Sstevel@tonic-gate printreg(char *s, ushort_t v, char *bits)
445*7c478bd9Sstevel@tonic-gate {
446*7c478bd9Sstevel@tonic-gate 	int i, any = 0;
447*7c478bd9Sstevel@tonic-gate 	char c;
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 	if (bits && *bits == 8)
450*7c478bd9Sstevel@tonic-gate 		(void) printf("%s = %o", s, v);
451*7c478bd9Sstevel@tonic-gate 	else
452*7c478bd9Sstevel@tonic-gate 		(void) printf("%s = %x", s, v);
453*7c478bd9Sstevel@tonic-gate 	bits++;
454*7c478bd9Sstevel@tonic-gate 	if (v && bits) {
455*7c478bd9Sstevel@tonic-gate 		(void) putchar('<');
456*7c478bd9Sstevel@tonic-gate 		while ((i = *bits++) != 0) {
457*7c478bd9Sstevel@tonic-gate 			if (v & (1 << (i-1))) {
458*7c478bd9Sstevel@tonic-gate 				if (any)
459*7c478bd9Sstevel@tonic-gate 					(void) putchar(',');
460*7c478bd9Sstevel@tonic-gate 				any = 1;
461*7c478bd9Sstevel@tonic-gate 				for (; (c = *bits) > 32; bits++)
462*7c478bd9Sstevel@tonic-gate 					(void) putchar(c);
463*7c478bd9Sstevel@tonic-gate 			} else
464*7c478bd9Sstevel@tonic-gate 				for (; *bits > 32; bits++)
465*7c478bd9Sstevel@tonic-gate 					;
466*7c478bd9Sstevel@tonic-gate 		}
467*7c478bd9Sstevel@tonic-gate 		(void) putchar('>');
468*7c478bd9Sstevel@tonic-gate 	}
469*7c478bd9Sstevel@tonic-gate }
470