xref: /csrg-svn/sys/pmax/dev/tz.c (revision 53086)
1 /*
2  * Copyright (c) 1992 Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ralph Campbell.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)tz.c	7.3 (Berkeley) 03/29/92
11  *
12  * from: $Header: /sprite/src/kernel/dev/RCS/devSCSITape.c,
13  *	v 8.14 89/07/31 17:26:13 mendel Exp $ SPRITE (Berkeley)
14  */
15 
16 /*
17  * SCSI CCS (Command Command Set) tape driver.
18  */
19 #include "tz.h"
20 #if NTZ > 0
21 
22 #include "param.h"
23 #include "systm.h"
24 #include "buf.h"
25 #include "errno.h"
26 #include "file.h"
27 #include "ioctl.h"
28 #include "mtio.h"
29 #include "syslog.h"
30 #include "tprintf.h"
31 
32 #include "device.h"
33 #include "scsi.h"
34 
35 int	tzprobe();
36 void	tzstart(), tzdone();
37 
38 struct	driver tzdriver = {
39 	"tz", tzprobe, tzstart, tzdone,
40 };
41 
42 struct	tz_softc {
43 	struct	scsi_device *sc_sd;	/* physical unit info */
44 	int	sc_flags;		/* see below */
45 	int	sc_tapeid;		/* tape drive id */
46 	int	sc_blklen;		/* 0 = variable len records */
47 	long	sc_numblks;		/* number of blocks on tape */
48 	tpr_t	sc_ctty;		/* terminal for error messages */
49 	struct	buf sc_tab;		/* queue of pending operations */
50 	struct	buf sc_buf;		/* buf for doing I/O */
51 	struct	buf sc_errbuf;		/* buf for doing REQUEST_SENSE */
52 	struct	ScsiCmd sc_cmd;		/* command for controller */
53 	ScsiGroup0Cmd sc_rwcmd;		/* SCSI cmd for read/write */
54 	struct	scsi_fmt_cdb sc_cdb;	/* SCSI cmd if not read/write */
55 	struct	scsi_fmt_sense sc_sense;	/* sense data from last cmd */
56 	struct	ScsiTapeModeSelectHdr sc_mode;	/* SCSI_MODE_SENSE data */
57 	char	sc_modelen;		/* SCSI_MODE_SENSE data length */
58 } tz_softc[NTZ];
59 
60 /* sc_flags values */
61 #define	TZF_ALIVE		0x01	/* drive found and ready */
62 #define	TZF_SENSEINPROGRESS	0x02	/* REQUEST_SENSE command in progress */
63 #define	TZF_ALTCMD		0x04	/* alternate command in progress */
64 #define	TZF_WRITTEN		0x08	/* tape has been written to */
65 #define	TZF_OPEN		0x10	/* device is open */
66 #define	TZF_WAIT		0x20	/* waiting for sc_tab to drain */
67 #define TZF_SEENEOF		0x40	/* seen file mark on read */
68 
69 /* bits in minor device */
70 #define	tzunit(x)	(minor(x) >> 4)	/* tz%d unit number */
71 #define TZ_NOREWIND	0x01		/* don't rewind on close */
72 #define TZ_HIDENSITY	0x02
73 #define TZ_EXSFMK	0x04
74 #define TZ_FIXEDBLK	0x08
75 
76 #ifdef DEBUG
77 int	tzdebug = 1;
78 #endif
79 
80 /*
81  * Test to see if device is present.
82  * Return true if found and initialized ok.
83  */
84 tzprobe(sd)
85 	struct scsi_device *sd;
86 {
87 	register struct tz_softc *sc = &tz_softc[sd->sd_unit];
88 	register int i;
89 	ScsiInquiryData inqbuf;
90 	ScsiClass7Sense *sp;
91 
92 	/* init some parameters that don't change */
93 	sc->sc_sd = sd;
94 	sc->sc_cmd.sd = sd;
95 	sc->sc_cmd.unit = sd->sd_unit;
96 	sc->sc_cmd.flags = 0;
97 	sc->sc_rwcmd.unitNumber = sd->sd_slave;
98 
99 	/* try to find out what type of device this is */
100 	sc->sc_flags = TZF_ALTCMD;	/* force use of sc_cdb */
101 	sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
102 	scsiGroup0Cmd(SCSI_INQUIRY, sd->sd_slave, 0, sizeof(inqbuf),
103 		(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
104 	sc->sc_buf.b_flags = B_BUSY | B_READ;
105 	sc->sc_buf.b_bcount = sizeof(inqbuf);
106 	sc->sc_buf.b_un.b_addr = (caddr_t)&inqbuf;
107 	sc->sc_buf.av_forw = (struct buf *)0;
108 	sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf;
109 	tzstart(sd->sd_unit);
110 	if (biowait(&sc->sc_buf) ||
111 	    (i = sizeof(inqbuf) - sc->sc_buf.b_resid) < 5)
112 		goto bad;
113 	if (inqbuf.type != SCSI_TAPE_TYPE || !inqbuf.rmb)
114 		goto bad;
115 
116 	/* check for device ready to clear UNIT_ATTN */
117 	sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
118 	scsiGroup0Cmd(SCSI_TEST_UNIT_READY, sd->sd_slave, 0, 0,
119 		(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
120 	sc->sc_buf.b_flags = B_BUSY | B_READ;
121 	sc->sc_buf.b_bcount = 0;
122 	sc->sc_buf.b_un.b_addr = (caddr_t)0;
123 	sc->sc_buf.av_forw = (struct buf *)0;
124 	sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf;
125 	tzstart(sd->sd_unit);
126 	(void) biowait(&sc->sc_buf);
127 
128 	sc->sc_flags = TZF_ALIVE;
129 	sc->sc_modelen = 12;
130 	sc->sc_buf.b_flags = 0;
131 	printf("tz%d at %s%d drive %d slave %d", sd->sd_unit,
132 		sd->sd_cdriver->d_name, sd->sd_ctlr, sd->sd_drive,
133 		sd->sd_slave);
134 	if (i == 5 && inqbuf.version == 1 && inqbuf.qualifier == 0x50) {
135 		printf(" TK50\n");
136 		sc->sc_tapeid = MT_ISTK50;
137 	} else if (i == 5 && inqbuf.version == 1 && inqbuf.qualifier == 0) {
138 		/* assume Emultex MT02 controller */
139 		printf(" MT02\n");
140 		sc->sc_tapeid = MT_ISMT02;
141 	} else if (inqbuf.version > 2 || i < 36) {
142 		printf(" GENERIC SCSI tape device: qual 0x%x, ver %d\n",
143 			inqbuf.qualifier, inqbuf.version);
144 		sc->sc_tapeid = 0;
145 	} else {
146 		char vid[9], pid[17], revl[5];
147 
148 		bcopy((caddr_t)inqbuf.vendorID, (caddr_t)vid, 8);
149 		bcopy((caddr_t)inqbuf.productID, (caddr_t)pid, 16);
150 		bcopy((caddr_t)inqbuf.revLevel, (caddr_t)revl, 4);
151 		for (i = 8; --i > 0; )
152 			if (vid[i] != ' ')
153 				break;
154 		vid[i+1] = 0;
155 		for (i = 16; --i > 0; )
156 			if (pid[i] != ' ')
157 				break;
158 		pid[i+1] = 0;
159 		for (i = 4; --i > 0; )
160 			if (revl[i] != ' ')
161 				break;
162 		revl[i+1] = 0;
163 		printf(" %s %s rev %s\n", vid, pid, revl);
164 
165 		if (bcmp("EXB-8200", pid, 8) == 0) {
166 			sc->sc_tapeid = MT_ISEXABYTE;
167 			sc->sc_modelen = 17;
168 		} else if (bcmp("VIPER 150", pid, 9) == 0) {
169 			sc->sc_tapeid = MT_ISVIPER1;
170 		} else if (bcmp("Python 25501", pid, 12) == 0) {
171 			sc->sc_tapeid = MT_ISPYTHON;
172 		} else if (bcmp("HP35450A", pid, 8) == 0) {
173 #if 0
174 			/* XXX "extra" stat makes the HP drive happy at boot time */
175 			stat = scsi_test_unit_rdy(ctlr, slave, unit);
176 #endif
177 			sc->sc_tapeid = MT_ISHPDAT;
178 		} else if (bcmp("123107 SCSI", pid, 11) == 0) {
179 			sc->sc_tapeid = MT_ISMFOUR;
180 		} else {
181 			printf("tz%d: assuming GENERIC SCSI tape device\n",
182 				sd->sd_unit,
183 				inqbuf.type, inqbuf.qualifier, inqbuf.version);
184 			sc->sc_tapeid = 0;
185 		}
186 	}
187 	return (1);
188 
189 bad:
190 	/* doesn't exist or not a CCS device */
191 	sc->sc_flags = 0;
192 	sc->sc_buf.b_flags = 0;
193 	return (0);
194 }
195 
196 /*
197  * Perform a special tape command on a SCSI Tape drive.
198  */
199 tzcommand(dev, command, code, count, data)
200 	dev_t dev;
201 	int command;
202 	int code;
203 	int count;
204 	caddr_t data;
205 {
206 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
207 	register ScsiGroup0Cmd *c;
208 	int s, error;
209 
210 	s = splbio();
211 	/* wait for pending operations to finish */
212 	while (sc->sc_tab.b_actf) {
213 		sc->sc_flags |= TZF_WAIT;
214 		sleep(&sc->sc_flags, PZERO);
215 	}
216 	sc->sc_flags |= TZF_ALTCMD;	/* force use of sc_cdb */
217 	sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
218 	c = (ScsiGroup0Cmd *)sc->sc_cdb.cdb;
219 	c->command = command;
220 	c->unitNumber = sc->sc_sd->sd_slave;
221 	c->highAddr = code;
222 	c->midAddr = count >> 16;
223 	c->lowAddr = count >> 8;
224 	c->blockCount = count;
225 	c->control = 0;
226 	if (command == SCSI_MODE_SELECT)
227 		sc->sc_buf.b_flags = B_BUSY;
228 	else {
229 		sc->sc_buf.b_flags = B_BUSY | B_READ;
230 #if 0
231 		/* this seems to work but doesn't give us a speed advantage */
232 		if (command == SCSI_TEST_UNIT_READY)
233 			sc->sc_cmd.flags |= SCSICMD_USE_SYNC;
234 #endif
235 	}
236 	sc->sc_buf.b_bcount = data ? count : 0;
237 	sc->sc_buf.b_un.b_addr = data;
238 	sc->sc_buf.av_forw = (struct buf *)0;
239 	sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf;
240 	tzstart(sc->sc_sd->sd_unit);
241 	error = biowait(&sc->sc_buf);
242 	sc->sc_flags &= ~TZF_ALTCMD;	/* force use of sc_cdb */
243 	sc->sc_buf.b_flags = 0;
244 	sc->sc_cmd.flags = 0;
245 	if (sc->sc_buf.b_resid)
246 		printf("tzcommand: resid %d\n", sc->sc_buf.b_resid); /* XXX */
247 	if (error == 0)
248 		switch (command) {
249 		case SCSI_SPACE:
250 		case SCSI_WRITE_EOF:
251 		case SCSI_REWIND:
252 			sc->sc_flags &= ~TZF_SEENEOF;
253 		}
254 	splx(s);
255 	return (error);
256 }
257 
258 void
259 tzstart(unit)
260 	int unit;
261 {
262 	register struct tz_softc *sc = &tz_softc[unit];
263 	register struct buf *bp = sc->sc_tab.b_actf;
264 	register int n;
265 
266 	sc->sc_cmd.buf = bp->b_un.b_addr;
267 	sc->sc_cmd.buflen = bp->b_bcount;
268 
269 	if (sc->sc_flags & (TZF_SENSEINPROGRESS | TZF_ALTCMD)) {
270 		if (bp->b_flags & B_READ)
271 			sc->sc_cmd.flags &= ~SCSICMD_DATA_TO_DEVICE;
272 		else
273 			sc->sc_cmd.flags |= SCSICMD_DATA_TO_DEVICE;
274 		sc->sc_cmd.cmd = sc->sc_cdb.cdb;
275 		sc->sc_cmd.cmdlen = sc->sc_cdb.len;
276 	} else {
277 		if (bp->b_flags & B_READ) {
278 			sc->sc_cmd.flags = 0;
279 			sc->sc_rwcmd.command = SCSI_READ;
280 			sc->sc_flags &= ~TZF_WRITTEN;
281 		} else {
282 			sc->sc_cmd.flags = SCSICMD_DATA_TO_DEVICE;
283 			sc->sc_rwcmd.command = SCSI_WRITE;
284 			sc->sc_flags |= TZF_WRITTEN;
285 		}
286 		sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd;
287 		sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd);
288 		if (sc->sc_blklen) {
289 			/* fixed sized records */
290 			n = bp->b_bcount / sc->sc_blklen;
291 			if (bp->b_bcount % sc->sc_blklen) {
292 				tprintf(sc->sc_ctty,
293 					"tz%d: I/O not block aligned %d/%ld\n",
294 					unit, sc->sc_blklen, bp->b_bcount);
295 				tzdone(unit, EIO, bp->b_bcount, 0);
296 			}
297 			sc->sc_rwcmd.highAddr = 1;
298 		} else {
299 			/* variable sized records */
300 			n = bp->b_bcount;
301 			sc->sc_rwcmd.highAddr = 0;
302 		}
303 		sc->sc_rwcmd.midAddr = n >> 16;
304 		sc->sc_rwcmd.lowAddr = n >> 8;
305 		sc->sc_rwcmd.blockCount = n;
306 	}
307 
308 	/* tell controller to start this command */
309 	(*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd);
310 }
311 
312 /*
313  * This is called by the controller driver when the command is done.
314  */
315 void
316 tzdone(unit, error, resid, status)
317 	int unit;
318 	int error;		/* error number from errno.h */
319 	int resid;		/* amount not transfered */
320 	int status;		/* SCSI status byte */
321 {
322 	register struct tz_softc *sc = &tz_softc[unit];
323 	register struct buf *bp = sc->sc_tab.b_actf;
324 	extern int cold;
325 
326 	if (bp == NULL) {
327 		printf("tz%d: bp == NULL\n", unit);
328 		return;
329 	}
330 	if (sc->sc_flags & TZF_SENSEINPROGRESS) {
331 		sc->sc_flags &= ~TZF_SENSEINPROGRESS;
332 		sc->sc_tab.b_actf = bp = bp->b_actf;	/* remove sc_errbuf */
333 #ifdef DIAGNOSTIC
334 		if (bp == 0)
335 			panic("tzdone");
336 #endif
337 
338 		if (error || (status & SCSI_STATUS_CHECKCOND)) {
339 #ifdef DEBUG
340 			if (tzdebug)
341 				printf("tz%d: error reading sense data: error %d scsi status 0x%x\n",
342 					unit, error, status);
343 #endif
344 			/*
345 			 * We got an error during the REQUEST_SENSE,
346 			 * fill in no sense for data.
347 			 */
348 			sc->sc_sense.sense[0] = 0x70;
349 			sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE;
350 		} else if (!cold) {
351 			ScsiClass7Sense *sp;
352 			long resid;
353 
354 			sp = (ScsiClass7Sense *)sc->sc_sense.sense;
355 			if (sp->error7 != 0x70)
356 				goto prerr;
357 			if (sp->valid) {
358 				resid = (sp->info1 << 24) | (sp->info2 << 16) |
359 					(sp->info3 << 8) | sp->info4;
360 				if (sc->sc_blklen)
361 					resid *= sc->sc_blklen;
362 			} else
363 				resid = 0;
364 			switch (sp->key) {
365 			case SCSI_CLASS7_NO_SENSE:
366 				/*
367 				 * Hit a filemark, end of media, or
368 				 * end of record.
369 				 * Fixed length blocks, an error.
370 				 */
371 				if (sp->endOfMedia) {
372 					bp->b_error = ENOSPC;
373 					bp->b_resid = resid;
374 					break;
375 				}
376 				if (sc->sc_blklen && sp->badBlockLen) {
377 					tprintf(sc->sc_ctty,
378 						"tz%d: Incorrect Block Length, expected %d got %d\n",
379 						unit, sc->sc_blklen, resid);
380 					break;
381 				}
382 				if (sp->fileMark)
383 					sc->sc_flags |= TZF_SEENEOF;
384 				bp->b_flags &= ~B_ERROR;
385 				bp->b_error = 0;
386 				bp->b_resid = resid;
387 				break;
388 
389 			case SCSI_CLASS7_UNIT_ATTN:
390 				if (!(sc->sc_flags & TZF_OPEN))
391 					break;
392 
393 			default:
394 			prerr:
395 				tprintf(sc->sc_ctty, "tz%d: ", unit);
396 				scsiPrintSense((ScsiClass7Sense *)
397 					sc->sc_sense.sense,
398 					sizeof(sc->sc_sense.sense) - resid);
399 			}
400 		}
401 	} else if (error || (status & SCSI_STATUS_CHECKCOND)) {
402 #ifdef DEBUG
403 		if (!cold && tzdebug)
404 			printf("tz%d: error %d scsi status 0x%x\n",
405 				unit, error, status);
406 #endif
407 		/* save error info */
408 		sc->sc_sense.status = status;
409 		bp->b_flags |= B_ERROR;
410 		bp->b_error = error;
411 		bp->b_resid = resid;
412 
413 		if (status & SCSI_STATUS_CHECKCOND) {
414 			/*
415 			 * Start a REQUEST_SENSE command.
416 			 * Since we are called at interrupt time, we can't
417 			 * wait for the command to finish; that's why we use
418 			 * the sc_flags field.
419 			 */
420 			sc->sc_flags |= TZF_SENSEINPROGRESS;
421 			sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
422 			scsiGroup0Cmd(SCSI_REQUEST_SENSE, sc->sc_sd->sd_slave,
423 				0, sizeof(sc->sc_sense.sense),
424 				(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
425 			sc->sc_errbuf.b_flags = B_BUSY | B_READ;
426 			sc->sc_errbuf.b_bcount = sizeof(sc->sc_sense.sense);
427 			sc->sc_errbuf.b_un.b_addr = (caddr_t)sc->sc_sense.sense;
428 			sc->sc_errbuf.av_forw = bp;
429 			sc->sc_tab.b_actf = &sc->sc_errbuf;
430 			tzstart(unit);
431 			return;
432 		}
433 	} else {
434 		sc->sc_sense.status = status;
435 		bp->b_resid = resid;
436 	}
437 
438 	sc->sc_tab.b_actf = bp->b_actf;
439 	biodone(bp);
440 	if (sc->sc_tab.b_actf)
441 		tzstart(unit);
442 	else {
443 		sc->sc_tab.b_active = 0;
444 		if (sc->sc_flags & TZF_WAIT) {
445 			sc->sc_flags &= ~TZF_WAIT;
446 			wakeup(&sc->sc_flags);
447 		}
448 	}
449 }
450 
451 /* ARGSUSED */
452 tzopen(dev, flags, type, p)
453 	dev_t dev;
454 	int flags, type;
455 	struct proc *p;
456 {
457 	register int unit = tzunit(dev);
458 	register struct tz_softc *sc = &tz_softc[unit];
459 	int error;
460 
461 	if (unit >= NTZ)
462 		return (ENXIO);
463 	if (!(sc->sc_flags & TZF_ALIVE)) {
464 		/* check again, tape may have been turned off at boot time */
465 		if (!tzprobe(sc->sc_sd))
466 			return (ENXIO);
467 	}
468 	if (sc->sc_flags & TZF_OPEN)
469 		return (EBUSY);
470 
471 	/* clear UNIT_ATTENTION */
472 	error = tzcommand(dev, SCSI_TEST_UNIT_READY, 0, 0, 0);
473 	if (error) {
474 		ScsiClass7Sense *sp = (ScsiClass7Sense *)sc->sc_sense.sense;
475 
476 		/* return error if last error was not UNIT_ATTENTION */
477 		if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND) ||
478 		    sp->error7 != 0x70 || sp->key != SCSI_CLASS7_UNIT_ATTN)
479 			return (error);
480 
481 		/*
482 		 * Try it again just to be sure and
483 		 * try to negotiate synchonous transfers.
484 		 */
485 		error = tzcommand(dev, SCSI_TEST_UNIT_READY, 0, 0, 0);
486 	}
487 
488 	/* get the current mode settings */
489 	error = tzcommand(dev, SCSI_MODE_SENSE, 0,
490 		sc->sc_modelen, (caddr_t)&sc->sc_mode);
491 	if (error)
492 		return (error);
493 
494 	/* check for write protected tape */
495 	if ((flags & FWRITE) && sc->sc_mode.writeprot) {
496 		uprintf("tz%d: write protected\n", unit);
497 		return (EACCES);
498 	}
499 
500 	/* set record length */
501 	switch (sc->sc_tapeid) {
502 	case MT_ISAR:
503 	case MT_ISHPDAT:
504 	case MT_ISVIPER1:
505 	case MT_ISPYTHON:
506 		sc->sc_blklen = 512;
507 		break;
508 
509 	case MT_ISEXABYTE:
510 #if 0
511 		if (minor(dev) & TZ_FIXEDBLK)
512 			sc->sc_blklen = 1024;
513 		else
514 			sc->sc_blklen = st_exblklen;
515 #endif
516 		break;
517 
518 	case MT_ISMFOUR:
519 	case MT_ISTK50:
520 		sc->sc_blklen = 0;
521 		break;
522 
523 	default:
524 		sc->sc_blklen = (sc->sc_mode.block_size2 << 16) |
525 			(sc->sc_mode.block_size1 << 8) | sc->sc_mode.block_size0;
526 	}
527 
528 	/* save total number of blocks on tape */
529 	sc->sc_numblks = (sc->sc_mode.blocks_2 << 16) |
530 		(sc->sc_mode.blocks_1 << 8) | sc->sc_mode.blocks_0;
531 
532 	/* setup for mode select */
533 	sc->sc_mode.len = 0;
534 	sc->sc_mode.media = 0;
535 	sc->sc_mode.bufferedMode = 1;
536 	sc->sc_mode.blocks_0 = 0;
537 	sc->sc_mode.blocks_1 = 0;
538 	sc->sc_mode.blocks_2 = 0;
539 	sc->sc_mode.block_size0 = sc->sc_blklen >> 16;
540 	sc->sc_mode.block_size1 = sc->sc_blklen >> 8;
541 	sc->sc_mode.block_size2 = sc->sc_blklen;
542 
543 	/* check for tape density changes */
544 	switch (sc->sc_tapeid) {
545 	case MT_ISAR:
546 		if (minor(dev) & TZ_HIDENSITY)
547 			sc->sc_mode.density = 0x5;
548 		else {
549 			if (flags & FWRITE) {
550 				uprintf("Can only write QIC-24\n");
551 				return (EIO);
552 			}
553 			sc->sc_mode.density = 0x4;
554 		}
555 		break;
556 
557 	case MT_ISMT02:
558 		/*
559 		 * The tape density is set automatically when the tape
560 		 * is loaded. We only need to change it if we are writing.
561 		 */
562 		if (flags & FWRITE) {
563 			if (minor(dev) & TZ_HIDENSITY)
564 				sc->sc_mode.density = 0;
565 			else
566 				sc->sc_mode.density = 0x4;
567 		}
568 		break;
569 
570 	case MT_ISEXABYTE:
571 #if 0
572 		if (minor(dev) & TZ_HIDENSITY)
573 			uprintf("EXB-8200 density support only\n");
574 		sc->sc_mode.vupb = (u_char)st_exvup;
575 		sc->sc_mode.rsvd5 = 0;
576 		sc->sc_mode.p5 = 0;
577 		sc->sc_mode.motionthres = (u_char)st_exmotthr;
578 		sc->sc_mode.reconthres = (u_char)st_exreconthr;
579 		sc->sc_mode.gapthres = (u_char)st_exgapthr;
580 #endif
581 		break;
582 
583 	case MT_ISHPDAT:
584 	case MT_ISVIPER1:
585 	case MT_ISPYTHON:
586 	case MT_ISTK50:
587 		if (minor(dev) & TZ_HIDENSITY)
588 			uprintf("tz%d: Only one density supported\n", unit);
589 		break;
590 
591 	case MT_ISMFOUR:
592 		break;		/* XXX could do density select? */
593 	}
594 
595 	/* set the current mode settings */
596 	error = tzcommand(dev, SCSI_MODE_SELECT, 0,
597 		sc->sc_modelen, (caddr_t)&sc->sc_mode);
598 	if (error)
599 		return (error);
600 
601 	sc->sc_ctty = tprintf_open(p);
602 	sc->sc_flags = TZF_ALIVE | TZF_OPEN;
603 	return (0);
604 }
605 
606 tzclose(dev, flag)
607 	dev_t dev;
608 	int flag;
609 {
610 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
611 	int error = 0;
612 
613 	if (!(sc->sc_flags & TZF_OPEN))
614 		return (0);
615 	if (flag == FWRITE ||
616 	    ((flag & FWRITE) && (sc->sc_flags & TZF_WRITTEN))) {
617 		error = tzcommand(dev, SCSI_WRITE_EOF, 0, 1, 0);
618 #if 0
619 		/*
620 		 * Cartridge tapes don't do double EOFs on EOT.
621 		 */
622 		switch (sc->sc_tapeid) {
623 		case MT_ISAR:
624 		case MT_ISMT02:
625 			break;
626 
627 		default:
628 			error = tzcommand(dev, SCSI_WRITE_EOF, 0, 1, 0);
629 			if (minor(dev) & TZ_NOREWIND)
630 				(void) tzcommand(dev, SCSI_SPACE, 0, -1, 0);
631 		}
632 #endif
633 	}
634 	if ((minor(dev) & TZ_NOREWIND) == 0)
635 		(void) tzcommand(dev, SCSI_REWIND, 0, 0, 0);
636 	sc->sc_flags &= ~(TZF_OPEN | TZF_WRITTEN);
637 	tprintf_close(sc->sc_ctty);
638 	return (error);
639 }
640 
641 tzioctl(dev, cmd, data, flag)
642 	dev_t dev;
643 	int cmd;
644 	caddr_t data;
645 	int flag;
646 {
647 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
648 	register struct buf *bp = &sc->sc_buf;
649 	struct mtop *mtop;
650 	struct mtget *mtget;
651 	int code, count;
652 	static tzops[] = {
653 		SCSI_WRITE_EOF, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE,
654 		SCSI_REWIND, SCSI_REWIND, SCSI_TEST_UNIT_READY
655 	};
656 
657 	switch (cmd) {
658 
659 	case MTIOCTOP:	/* tape operation */
660 		mtop = (struct mtop *)data;
661 		if ((unsigned)mtop->mt_op < MTREW && mtop->mt_count <= 0)
662 			return (EINVAL);
663 		switch (mtop->mt_op) {
664 
665 		case MTWEOF:
666 			code = 0;
667 			count = mtop->mt_count;
668 			break;
669 
670 		case MTFSF:
671 			code = 1;
672 			count = mtop->mt_count;
673 			break;
674 
675 		case MTBSF:
676 			code = 1;
677 			count = -mtop->mt_count;
678 			break;
679 
680 		case MTFSR:
681 			code = 0;
682 			count = mtop->mt_count;
683 			break;
684 
685 		case MTBSR:
686 			code = 0;
687 			count = -mtop->mt_count;
688 			break;
689 
690 		case MTREW:
691 		case MTOFFL:
692 		case MTNOP:
693 			code = 0;
694 			count = 0;
695 			break;
696 
697 		default:
698 			return (EINVAL);
699 		}
700 		return (tzcommand(dev, tzops[mtop->mt_op], code, count, 0));
701 
702 	case MTIOCGET:
703 		mtget = (struct mtget *)data;
704 		mtget->mt_dsreg = 0;
705 		mtget->mt_erreg = sc->sc_sense.status;
706 		mtget->mt_resid = 0;
707 		mtget->mt_type = 0;
708 		break;
709 
710 	default:
711 		return (EINVAL);
712 	}
713 	return (0);
714 }
715 
716 void
717 tzstrategy(bp)
718 	register struct buf *bp;
719 {
720 	register int unit = tzunit(bp->b_dev);
721 	register struct tz_softc *sc = &tz_softc[unit];
722 	register struct buf *dp;
723 	register int s;
724 
725 	if (sc->sc_flags & TZF_SEENEOF) {
726 		bp->b_resid = bp->b_bcount;
727 		biodone(bp);
728 		return;
729 	}
730 	bp->av_forw = NULL;
731 	dp = &sc->sc_tab;
732 	s = splbio();
733 	if (dp->b_actf == NULL)
734 		dp->b_actf = bp;
735 	else
736 		dp->b_actl->av_forw = bp;
737 	dp->b_actl = bp;
738 	if (dp->b_active == 0) {
739 		dp->b_active = 1;
740 		tzstart(unit);
741 	}
742 	splx(s);
743 }
744 #endif
745