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