xref: /csrg-svn/sys/pmax/dev/tz.c (revision 69799)
152130Smckusick /*
263638Sbostic  * Copyright (c) 1992, 1993
363638Sbostic  *	The Regents of the University of California.  All rights reserved.
452130Smckusick  *
552130Smckusick  * This code is derived from software contributed to Berkeley by
652130Smckusick  * Ralph Campbell.
752130Smckusick  *
852130Smckusick  * %sccs.include.redist.c%
952130Smckusick  *
10*69799Sralph  *	@(#)tz.c	8.5 (Berkeley) 06/02/95
1152130Smckusick  *
1252130Smckusick  * from: $Header: /sprite/src/kernel/dev/RCS/devSCSITape.c,
1352130Smckusick  *	v 8.14 89/07/31 17:26:13 mendel Exp $ SPRITE (Berkeley)
1452130Smckusick  */
1552130Smckusick 
1652130Smckusick /*
1752130Smckusick  * SCSI CCS (Command Command Set) tape driver.
1852130Smckusick  */
1952130Smckusick #include "tz.h"
2052130Smckusick #if NTZ > 0
2152130Smckusick 
2256522Sbostic #include <sys/param.h>
2356522Sbostic #include <sys/systm.h>
2456522Sbostic #include <sys/buf.h>
2556522Sbostic #include <sys/errno.h>
2656522Sbostic #include <sys/file.h>
2756522Sbostic #include <sys/ioctl.h>
2856522Sbostic #include <sys/mtio.h>
2956522Sbostic #include <sys/syslog.h>
3056522Sbostic #include <sys/tprintf.h>
3152130Smckusick 
3256525Sbostic #include <pmax/dev/device.h>
3356525Sbostic #include <pmax/dev/scsi.h>
3452130Smckusick 
3552130Smckusick int	tzprobe();
3652130Smckusick void	tzstart(), tzdone();
3752130Smckusick 
3852130Smckusick struct	driver tzdriver = {
3952130Smckusick 	"tz", tzprobe, tzstart, tzdone,
4052130Smckusick };
4152130Smckusick 
4252130Smckusick struct	tz_softc {
4352130Smckusick 	struct	scsi_device *sc_sd;	/* physical unit info */
4452130Smckusick 	int	sc_flags;		/* see below */
4553086Sralph 	int	sc_tapeid;		/* tape drive id */
4653086Sralph 	int	sc_blklen;		/* 0 = variable len records */
4753086Sralph 	long	sc_numblks;		/* number of blocks on tape */
4853086Sralph 	tpr_t	sc_ctty;		/* terminal for error messages */
4952130Smckusick 	struct	buf sc_tab;		/* queue of pending operations */
5052130Smckusick 	struct	buf sc_buf;		/* buf for doing I/O */
5152130Smckusick 	struct	buf sc_errbuf;		/* buf for doing REQUEST_SENSE */
5252130Smckusick 	struct	ScsiCmd sc_cmd;		/* command for controller */
5352130Smckusick 	ScsiGroup0Cmd sc_rwcmd;		/* SCSI cmd for read/write */
5452130Smckusick 	struct	scsi_fmt_cdb sc_cdb;	/* SCSI cmd if not read/write */
5552130Smckusick 	struct	scsi_fmt_sense sc_sense;	/* sense data from last cmd */
5653086Sralph 	struct	ScsiTapeModeSelectHdr sc_mode;	/* SCSI_MODE_SENSE data */
5753086Sralph 	char	sc_modelen;		/* SCSI_MODE_SENSE data length */
5852130Smckusick } tz_softc[NTZ];
5952130Smckusick 
6052130Smckusick /* sc_flags values */
6152130Smckusick #define	TZF_ALIVE		0x01	/* drive found and ready */
6252130Smckusick #define	TZF_SENSEINPROGRESS	0x02	/* REQUEST_SENSE command in progress */
6352130Smckusick #define	TZF_ALTCMD		0x04	/* alternate command in progress */
6452130Smckusick #define	TZF_WRITTEN		0x08	/* tape has been written to */
6552130Smckusick #define	TZF_OPEN		0x10	/* device is open */
6652130Smckusick #define	TZF_WAIT		0x20	/* waiting for sc_tab to drain */
6753086Sralph #define TZF_SEENEOF		0x40	/* seen file mark on read */
6852130Smckusick 
6952130Smckusick /* bits in minor device */
7053086Sralph #define	tzunit(x)	(minor(x) >> 4)	/* tz%d unit number */
7153086Sralph #define TZ_NOREWIND	0x01		/* don't rewind on close */
7253086Sralph #define TZ_HIDENSITY	0x02
7353086Sralph #define TZ_EXSFMK	0x04
7453086Sralph #define TZ_FIXEDBLK	0x08
7552130Smckusick 
7652130Smckusick #ifdef DEBUG
7759068Sralph int	tzdebug = 0;
7852130Smckusick #endif
7952130Smckusick 
8052130Smckusick /*
8152130Smckusick  * Test to see if device is present.
8252130Smckusick  * Return true if found and initialized ok.
8352130Smckusick  */
8452130Smckusick tzprobe(sd)
8552130Smckusick 	struct scsi_device *sd;
8652130Smckusick {
8752130Smckusick 	register struct tz_softc *sc = &tz_softc[sd->sd_unit];
8852130Smckusick 	register int i;
8952130Smckusick 	ScsiInquiryData inqbuf;
9052130Smckusick 	ScsiClass7Sense *sp;
9152130Smckusick 
9252130Smckusick 	/* init some parameters that don't change */
9352130Smckusick 	sc->sc_sd = sd;
9452130Smckusick 	sc->sc_cmd.sd = sd;
9552130Smckusick 	sc->sc_cmd.unit = sd->sd_unit;
9653086Sralph 	sc->sc_cmd.flags = 0;
9752130Smckusick 	sc->sc_rwcmd.unitNumber = sd->sd_slave;
9852130Smckusick 
9952130Smckusick 	/* try to find out what type of device this is */
10052130Smckusick 	sc->sc_flags = TZF_ALTCMD;	/* force use of sc_cdb */
10152130Smckusick 	sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
10252130Smckusick 	scsiGroup0Cmd(SCSI_INQUIRY, sd->sd_slave, 0, sizeof(inqbuf),
10352130Smckusick 		(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
10452130Smckusick 	sc->sc_buf.b_flags = B_BUSY | B_READ;
10552130Smckusick 	sc->sc_buf.b_bcount = sizeof(inqbuf);
10652130Smckusick 	sc->sc_buf.b_un.b_addr = (caddr_t)&inqbuf;
10756630Sralph 	sc->sc_buf.b_actf = (struct buf *)0;
10856630Sralph 	sc->sc_buf.b_actb = &sc->sc_tab.b_actf;
10956630Sralph 	sc->sc_tab.b_actf = &sc->sc_buf;
11056630Sralph 	sc->sc_tab.b_actb = &sc->sc_buf.b_actf;
11152130Smckusick 	tzstart(sd->sd_unit);
11252130Smckusick 	if (biowait(&sc->sc_buf) ||
11352130Smckusick 	    (i = sizeof(inqbuf) - sc->sc_buf.b_resid) < 5)
11452130Smckusick 		goto bad;
11553086Sralph 	if (inqbuf.type != SCSI_TAPE_TYPE || !inqbuf.rmb)
11652130Smckusick 		goto bad;
11752130Smckusick 
11852130Smckusick 	/* check for device ready to clear UNIT_ATTN */
11952130Smckusick 	sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
12052130Smckusick 	scsiGroup0Cmd(SCSI_TEST_UNIT_READY, sd->sd_slave, 0, 0,
12152130Smckusick 		(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
12252130Smckusick 	sc->sc_buf.b_flags = B_BUSY | B_READ;
12352130Smckusick 	sc->sc_buf.b_bcount = 0;
12452130Smckusick 	sc->sc_buf.b_un.b_addr = (caddr_t)0;
12556630Sralph 	sc->sc_buf.b_actf = (struct buf *)0;
12656630Sralph 	sc->sc_buf.b_actb = &sc->sc_tab.b_actf;
12756630Sralph 	sc->sc_tab.b_actf = &sc->sc_buf;
12856630Sralph 	sc->sc_tab.b_actb = &sc->sc_buf.b_actf;
12952130Smckusick 	tzstart(sd->sd_unit);
13052130Smckusick 	(void) biowait(&sc->sc_buf);
13152130Smckusick 
13252130Smckusick 	sc->sc_flags = TZF_ALIVE;
13353086Sralph 	sc->sc_modelen = 12;
13452130Smckusick 	sc->sc_buf.b_flags = 0;
13553086Sralph 	printf("tz%d at %s%d drive %d slave %d", sd->sd_unit,
13652130Smckusick 		sd->sd_cdriver->d_name, sd->sd_ctlr, sd->sd_drive,
13752130Smckusick 		sd->sd_slave);
13853086Sralph 	if (i == 5 && inqbuf.version == 1 && inqbuf.qualifier == 0x50) {
13953086Sralph 		printf(" TK50\n");
14053086Sralph 		sc->sc_tapeid = MT_ISTK50;
14165432Smckusick 	} else if (i >= 5 && inqbuf.version == 1 && inqbuf.qualifier == 0 &&
14264976Smckusick 	    inqbuf.length == 0) {
14353086Sralph 		/* assume Emultex MT02 controller */
14453086Sralph 		printf(" MT02\n");
14553086Sralph 		sc->sc_tapeid = MT_ISMT02;
14653086Sralph 	} else if (inqbuf.version > 2 || i < 36) {
14753086Sralph 		printf(" GENERIC SCSI tape device: qual 0x%x, ver %d\n",
14853086Sralph 			inqbuf.qualifier, inqbuf.version);
14953086Sralph 		sc->sc_tapeid = 0;
15053086Sralph 	} else {
15153086Sralph 		char vid[9], pid[17], revl[5];
15253086Sralph 
15353086Sralph 		bcopy((caddr_t)inqbuf.vendorID, (caddr_t)vid, 8);
15453086Sralph 		bcopy((caddr_t)inqbuf.productID, (caddr_t)pid, 16);
15553086Sralph 		bcopy((caddr_t)inqbuf.revLevel, (caddr_t)revl, 4);
15653086Sralph 		for (i = 8; --i > 0; )
15753086Sralph 			if (vid[i] != ' ')
15853086Sralph 				break;
15953086Sralph 		vid[i+1] = 0;
16053086Sralph 		for (i = 16; --i > 0; )
16153086Sralph 			if (pid[i] != ' ')
16253086Sralph 				break;
16353086Sralph 		pid[i+1] = 0;
16453086Sralph 		for (i = 4; --i > 0; )
16553086Sralph 			if (revl[i] != ' ')
16653086Sralph 				break;
16753086Sralph 		revl[i+1] = 0;
16853086Sralph 		printf(" %s %s rev %s\n", vid, pid, revl);
16953086Sralph 
17053086Sralph 		if (bcmp("EXB-8200", pid, 8) == 0) {
17153086Sralph 			sc->sc_tapeid = MT_ISEXABYTE;
17253086Sralph 			sc->sc_modelen = 17;
17353086Sralph 		} else if (bcmp("VIPER 150", pid, 9) == 0) {
17453086Sralph 			sc->sc_tapeid = MT_ISVIPER1;
17553086Sralph 		} else if (bcmp("Python 25501", pid, 12) == 0) {
17653086Sralph 			sc->sc_tapeid = MT_ISPYTHON;
17753086Sralph 		} else if (bcmp("HP35450A", pid, 8) == 0) {
17853086Sralph #if 0
17953086Sralph 			/* XXX "extra" stat makes the HP drive happy at boot time */
18053086Sralph 			stat = scsi_test_unit_rdy(ctlr, slave, unit);
18153086Sralph #endif
18253086Sralph 			sc->sc_tapeid = MT_ISHPDAT;
18353086Sralph 		} else if (bcmp("123107 SCSI", pid, 11) == 0) {
18453086Sralph 			sc->sc_tapeid = MT_ISMFOUR;
18553086Sralph 		} else {
18653086Sralph 			printf("tz%d: assuming GENERIC SCSI tape device\n",
18753086Sralph 				sd->sd_unit,
18853086Sralph 				inqbuf.type, inqbuf.qualifier, inqbuf.version);
18953086Sralph 			sc->sc_tapeid = 0;
19053086Sralph 		}
19153086Sralph 	}
19252130Smckusick 	return (1);
19352130Smckusick 
19452130Smckusick bad:
19552130Smckusick 	/* doesn't exist or not a CCS device */
19652130Smckusick 	sc->sc_flags = 0;
19752130Smckusick 	sc->sc_buf.b_flags = 0;
19852130Smckusick 	return (0);
19952130Smckusick }
20052130Smckusick 
20152130Smckusick /*
20252130Smckusick  * Perform a special tape command on a SCSI Tape drive.
20352130Smckusick  */
tzcommand(dev,command,code,count,data)20453086Sralph tzcommand(dev, command, code, count, data)
20552130Smckusick 	dev_t dev;
20652130Smckusick 	int command;
20752130Smckusick 	int code;
20852130Smckusick 	int count;
20953086Sralph 	caddr_t data;
21052130Smckusick {
21152130Smckusick 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
21253086Sralph 	register ScsiGroup0Cmd *c;
21352130Smckusick 	int s, error;
21452130Smckusick 
21552130Smckusick 	s = splbio();
21653086Sralph 	/* wait for pending operations to finish */
21752130Smckusick 	while (sc->sc_tab.b_actf) {
21852130Smckusick 		sc->sc_flags |= TZF_WAIT;
21952130Smckusick 		sleep(&sc->sc_flags, PZERO);
22052130Smckusick 	}
22152130Smckusick 	sc->sc_flags |= TZF_ALTCMD;	/* force use of sc_cdb */
22252130Smckusick 	sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
22353086Sralph 	c = (ScsiGroup0Cmd *)sc->sc_cdb.cdb;
22453086Sralph 	c->command = command;
22553086Sralph 	c->unitNumber = sc->sc_sd->sd_slave;
22653086Sralph 	c->highAddr = code;
22753086Sralph 	c->midAddr = count >> 16;
22853086Sralph 	c->lowAddr = count >> 8;
22953086Sralph 	c->blockCount = count;
23053086Sralph 	c->control = 0;
23153086Sralph 	if (command == SCSI_MODE_SELECT)
23253086Sralph 		sc->sc_buf.b_flags = B_BUSY;
23353086Sralph 	else {
23453086Sralph 		sc->sc_buf.b_flags = B_BUSY | B_READ;
23553086Sralph #if 0
23653086Sralph 		/* this seems to work but doesn't give us a speed advantage */
23753086Sralph 		if (command == SCSI_TEST_UNIT_READY)
23853086Sralph 			sc->sc_cmd.flags |= SCSICMD_USE_SYNC;
23953086Sralph #endif
24053086Sralph 	}
24153086Sralph 	sc->sc_buf.b_bcount = data ? count : 0;
24253086Sralph 	sc->sc_buf.b_un.b_addr = data;
24356630Sralph 	sc->sc_buf.b_actf = (struct buf *)0;
24456630Sralph 	sc->sc_buf.b_actb = &sc->sc_tab.b_actf;
24556630Sralph 	sc->sc_tab.b_actf = &sc->sc_buf;
24656630Sralph 	sc->sc_tab.b_actb = &sc->sc_buf.b_actf;
24752130Smckusick 	tzstart(sc->sc_sd->sd_unit);
24852130Smckusick 	error = biowait(&sc->sc_buf);
24952130Smckusick 	sc->sc_flags &= ~TZF_ALTCMD;	/* force use of sc_cdb */
25052130Smckusick 	sc->sc_buf.b_flags = 0;
25153086Sralph 	sc->sc_cmd.flags = 0;
25253086Sralph 	if (sc->sc_buf.b_resid)
25353086Sralph 		printf("tzcommand: resid %d\n", sc->sc_buf.b_resid); /* XXX */
25453086Sralph 	if (error == 0)
25553086Sralph 		switch (command) {
25653086Sralph 		case SCSI_SPACE:
25753086Sralph 		case SCSI_WRITE_EOF:
25853086Sralph 		case SCSI_REWIND:
25953086Sralph 			sc->sc_flags &= ~TZF_SEENEOF;
26053086Sralph 		}
26152130Smckusick 	splx(s);
26252130Smckusick 	return (error);
26352130Smckusick }
26452130Smckusick 
26552130Smckusick void
tzstart(unit)26652130Smckusick tzstart(unit)
26752130Smckusick 	int unit;
26852130Smckusick {
26952130Smckusick 	register struct tz_softc *sc = &tz_softc[unit];
27052130Smckusick 	register struct buf *bp = sc->sc_tab.b_actf;
27152130Smckusick 	register int n;
27252130Smckusick 
27352130Smckusick 	sc->sc_cmd.buf = bp->b_un.b_addr;
27452130Smckusick 	sc->sc_cmd.buflen = bp->b_bcount;
27552130Smckusick 
27652130Smckusick 	if (sc->sc_flags & (TZF_SENSEINPROGRESS | TZF_ALTCMD)) {
27753086Sralph 		if (bp->b_flags & B_READ)
27853086Sralph 			sc->sc_cmd.flags &= ~SCSICMD_DATA_TO_DEVICE;
27953086Sralph 		else
28053086Sralph 			sc->sc_cmd.flags |= SCSICMD_DATA_TO_DEVICE;
28152130Smckusick 		sc->sc_cmd.cmd = sc->sc_cdb.cdb;
28252130Smckusick 		sc->sc_cmd.cmdlen = sc->sc_cdb.len;
28352130Smckusick 	} else {
28452130Smckusick 		if (bp->b_flags & B_READ) {
28552861Sralph 			sc->sc_cmd.flags = 0;
28652130Smckusick 			sc->sc_rwcmd.command = SCSI_READ;
28753086Sralph 			sc->sc_flags &= ~TZF_WRITTEN;
28852130Smckusick 		} else {
28952861Sralph 			sc->sc_cmd.flags = SCSICMD_DATA_TO_DEVICE;
29052130Smckusick 			sc->sc_rwcmd.command = SCSI_WRITE;
29153086Sralph 			sc->sc_flags |= TZF_WRITTEN;
29252130Smckusick 		}
29352130Smckusick 		sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd;
29452130Smckusick 		sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd);
29553086Sralph 		if (sc->sc_blklen) {
29653086Sralph 			/* fixed sized records */
29753086Sralph 			n = bp->b_bcount / sc->sc_blklen;
29853086Sralph 			if (bp->b_bcount % sc->sc_blklen) {
29953086Sralph 				tprintf(sc->sc_ctty,
30053086Sralph 					"tz%d: I/O not block aligned %d/%ld\n",
30153086Sralph 					unit, sc->sc_blklen, bp->b_bcount);
30253086Sralph 				tzdone(unit, EIO, bp->b_bcount, 0);
30353086Sralph 			}
30453086Sralph 			sc->sc_rwcmd.highAddr = 1;
30553086Sralph 		} else {
30653086Sralph 			/* variable sized records */
30753086Sralph 			n = bp->b_bcount;
30853086Sralph 			sc->sc_rwcmd.highAddr = 0;
30953086Sralph 		}
31052130Smckusick 		sc->sc_rwcmd.midAddr = n >> 16;
31152130Smckusick 		sc->sc_rwcmd.lowAddr = n >> 8;
31252130Smckusick 		sc->sc_rwcmd.blockCount = n;
31352130Smckusick 	}
31452130Smckusick 
31552130Smckusick 	/* tell controller to start this command */
31652130Smckusick 	(*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd);
31752130Smckusick }
31852130Smckusick 
31952130Smckusick /*
32052130Smckusick  * This is called by the controller driver when the command is done.
32152130Smckusick  */
32252130Smckusick void
tzdone(unit,error,resid,status)32352130Smckusick tzdone(unit, error, resid, status)
32452130Smckusick 	int unit;
32552130Smckusick 	int error;		/* error number from errno.h */
32652130Smckusick 	int resid;		/* amount not transfered */
32752130Smckusick 	int status;		/* SCSI status byte */
32852130Smckusick {
32952130Smckusick 	register struct tz_softc *sc = &tz_softc[unit];
33052130Smckusick 	register struct buf *bp = sc->sc_tab.b_actf;
33156630Sralph 	register struct buf *dp;
33252130Smckusick 	extern int cold;
33352130Smckusick 
33452130Smckusick 	if (bp == NULL) {
33552130Smckusick 		printf("tz%d: bp == NULL\n", unit);
33652130Smckusick 		return;
33752130Smckusick 	}
33852130Smckusick 	if (sc->sc_flags & TZF_SENSEINPROGRESS) {
33952130Smckusick 		sc->sc_flags &= ~TZF_SENSEINPROGRESS;
34056630Sralph 		*bp->b_actb = dp = bp->b_actf;	/* remove sc_errbuf */
34153086Sralph #ifdef DIAGNOSTIC
34256630Sralph 		if (!dp)
34353086Sralph 			panic("tzdone");
34453086Sralph #endif
34556630Sralph 		dp->b_actb = bp->b_actb;
34656630Sralph 		bp = dp;
34752130Smckusick 
34852130Smckusick 		if (error || (status & SCSI_STATUS_CHECKCOND)) {
34953201Sralph 			printf("tz%d: error reading sense data: error %d scsi status 0x%x\n",
35053201Sralph 				unit, error, status);
35152130Smckusick 			/*
35252130Smckusick 			 * We got an error during the REQUEST_SENSE,
35352130Smckusick 			 * fill in no sense for data.
35452130Smckusick 			 */
35552130Smckusick 			sc->sc_sense.sense[0] = 0x70;
35652130Smckusick 			sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE;
35753086Sralph 		} else if (!cold) {
35853086Sralph 			ScsiClass7Sense *sp;
35953086Sralph 			long resid;
36053086Sralph 
36153086Sralph 			sp = (ScsiClass7Sense *)sc->sc_sense.sense;
36253086Sralph 			if (sp->error7 != 0x70)
36353086Sralph 				goto prerr;
36453086Sralph 			if (sp->valid) {
36553086Sralph 				resid = (sp->info1 << 24) | (sp->info2 << 16) |
36653086Sralph 					(sp->info3 << 8) | sp->info4;
36753086Sralph 				if (sc->sc_blklen)
36853086Sralph 					resid *= sc->sc_blklen;
36953086Sralph 			} else
37053086Sralph 				resid = 0;
37153086Sralph 			switch (sp->key) {
37253086Sralph 			case SCSI_CLASS7_NO_SENSE:
37353086Sralph 				/*
37453086Sralph 				 * Hit a filemark, end of media, or
37553086Sralph 				 * end of record.
37653086Sralph 				 * Fixed length blocks, an error.
37753086Sralph 				 */
37853086Sralph 				if (sp->endOfMedia) {
37953086Sralph 					bp->b_error = ENOSPC;
38053086Sralph 					bp->b_resid = resid;
38153086Sralph 					break;
38253086Sralph 				}
38353086Sralph 				if (sc->sc_blklen && sp->badBlockLen) {
38453086Sralph 					tprintf(sc->sc_ctty,
38553086Sralph 						"tz%d: Incorrect Block Length, expected %d got %d\n",
38653086Sralph 						unit, sc->sc_blklen, resid);
38753086Sralph 					break;
38853086Sralph 				}
38956630Sralph 				if (resid < 0) {
39056630Sralph 					/*
39156630Sralph 					 * Variable length records but
39256630Sralph 					 * attempted to read less than a
39356630Sralph 					 * full record.
39456630Sralph 					 */
39556630Sralph 					tprintf(sc->sc_ctty,
39656630Sralph 						"tz%d: Partial Read of Variable Length Tape Block, expected %d read %d\n",
39756630Sralph 						unit, bp->b_bcount - resid,
39856630Sralph 						bp->b_bcount);
39956630Sralph 					bp->b_resid = 0;
40056630Sralph 					break;
40156630Sralph 				}
40253086Sralph 				if (sp->fileMark)
40353086Sralph 					sc->sc_flags |= TZF_SEENEOF;
40456630Sralph 				/*
40556630Sralph 				 * Attempting to read more than a record is
40656630Sralph 				 * OK. Just record how much was actually read.
40756630Sralph 				 */
40853086Sralph 				bp->b_flags &= ~B_ERROR;
40953086Sralph 				bp->b_error = 0;
41053086Sralph 				bp->b_resid = resid;
41153086Sralph 				break;
41253086Sralph 
41353086Sralph 			case SCSI_CLASS7_UNIT_ATTN:
41453086Sralph 				if (!(sc->sc_flags & TZF_OPEN))
41553086Sralph 					break;
41653086Sralph 
41753086Sralph 			default:
41853086Sralph 			prerr:
41965596Smckusick 				printf("tz%d: ", unit);
42053086Sralph 				scsiPrintSense((ScsiClass7Sense *)
42153086Sralph 					sc->sc_sense.sense,
42253086Sralph 					sizeof(sc->sc_sense.sense) - resid);
42353086Sralph 			}
42452130Smckusick 		}
42552130Smckusick 	} else if (error || (status & SCSI_STATUS_CHECKCOND)) {
42652130Smckusick #ifdef DEBUG
42753086Sralph 		if (!cold && tzdebug)
42852130Smckusick 			printf("tz%d: error %d scsi status 0x%x\n",
42952130Smckusick 				unit, error, status);
43052130Smckusick #endif
43152130Smckusick 		/* save error info */
43252130Smckusick 		sc->sc_sense.status = status;
43352130Smckusick 		bp->b_flags |= B_ERROR;
43452130Smckusick 		bp->b_error = error;
43552130Smckusick 		bp->b_resid = resid;
43652130Smckusick 
43752130Smckusick 		if (status & SCSI_STATUS_CHECKCOND) {
43852130Smckusick 			/*
43952130Smckusick 			 * Start a REQUEST_SENSE command.
44052130Smckusick 			 * Since we are called at interrupt time, we can't
44152130Smckusick 			 * wait for the command to finish; that's why we use
44252130Smckusick 			 * the sc_flags field.
44352130Smckusick 			 */
44452130Smckusick 			sc->sc_flags |= TZF_SENSEINPROGRESS;
44552130Smckusick 			sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
44652130Smckusick 			scsiGroup0Cmd(SCSI_REQUEST_SENSE, sc->sc_sd->sd_slave,
44752130Smckusick 				0, sizeof(sc->sc_sense.sense),
44852130Smckusick 				(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
44956630Sralph 			sc->sc_errbuf.b_flags = B_BUSY | B_PHYS | B_READ;
45052130Smckusick 			sc->sc_errbuf.b_bcount = sizeof(sc->sc_sense.sense);
45152130Smckusick 			sc->sc_errbuf.b_un.b_addr = (caddr_t)sc->sc_sense.sense;
45256630Sralph 			sc->sc_errbuf.b_actf = bp;
45356630Sralph 			sc->sc_errbuf.b_actb = bp->b_actb;
45456630Sralph 			*bp->b_actb = &sc->sc_errbuf;
45556630Sralph 			bp->b_actb = &sc->sc_errbuf.b_actf;
45652130Smckusick 			tzstart(unit);
45752130Smckusick 			return;
45852130Smckusick 		}
45952130Smckusick 	} else {
46052130Smckusick 		sc->sc_sense.status = status;
46152130Smckusick 		bp->b_resid = resid;
46252130Smckusick 	}
46352130Smckusick 
46456630Sralph 	if (dp = bp->b_actf)
46556630Sralph 		dp->b_actb = bp->b_actb;
46656630Sralph 	else
46756630Sralph 		sc->sc_tab.b_actb = bp->b_actb;
46856630Sralph 	*bp->b_actb = dp;
46952130Smckusick 	biodone(bp);
47052130Smckusick 	if (sc->sc_tab.b_actf)
47152130Smckusick 		tzstart(unit);
47252130Smckusick 	else {
47352130Smckusick 		sc->sc_tab.b_active = 0;
47452130Smckusick 		if (sc->sc_flags & TZF_WAIT) {
47552130Smckusick 			sc->sc_flags &= ~TZF_WAIT;
47652130Smckusick 			wakeup(&sc->sc_flags);
47752130Smckusick 		}
47852130Smckusick 	}
47952130Smckusick }
48052130Smckusick 
48153086Sralph /* ARGSUSED */
tzopen(dev,flags,type,p)48253086Sralph tzopen(dev, flags, type, p)
48352130Smckusick 	dev_t dev;
48453086Sralph 	int flags, type;
48553086Sralph 	struct proc *p;
48652130Smckusick {
48752130Smckusick 	register int unit = tzunit(dev);
48852130Smckusick 	register struct tz_softc *sc = &tz_softc[unit];
48952130Smckusick 	int error;
49052130Smckusick 
49163637Smckusick 	if (unit >= NTZ || sc->sc_sd == NULL)
49252130Smckusick 		return (ENXIO);
49352130Smckusick 	if (!(sc->sc_flags & TZF_ALIVE)) {
49452130Smckusick 		/* check again, tape may have been turned off at boot time */
49552130Smckusick 		if (!tzprobe(sc->sc_sd))
49652130Smckusick 			return (ENXIO);
49752130Smckusick 	}
49852130Smckusick 	if (sc->sc_flags & TZF_OPEN)
49952130Smckusick 		return (EBUSY);
50052130Smckusick 
50152130Smckusick 	/* clear UNIT_ATTENTION */
50253086Sralph 	error = tzcommand(dev, SCSI_TEST_UNIT_READY, 0, 0, 0);
50356630Sralph 	while (error) {
50452130Smckusick 		ScsiClass7Sense *sp = (ScsiClass7Sense *)sc->sc_sense.sense;
50552130Smckusick 
50652130Smckusick 		/* return error if last error was not UNIT_ATTENTION */
50752130Smckusick 		if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND) ||
50852130Smckusick 		    sp->error7 != 0x70 || sp->key != SCSI_CLASS7_UNIT_ATTN)
50952130Smckusick 			return (error);
51053086Sralph 
51153086Sralph 		/*
51253086Sralph 		 * Try it again just to be sure and
51353086Sralph 		 * try to negotiate synchonous transfers.
51453086Sralph 		 */
51553086Sralph 		error = tzcommand(dev, SCSI_TEST_UNIT_READY, 0, 0, 0);
51652130Smckusick 	}
51752130Smckusick 
51853086Sralph 	/* get the current mode settings */
51953086Sralph 	error = tzcommand(dev, SCSI_MODE_SENSE, 0,
52053086Sralph 		sc->sc_modelen, (caddr_t)&sc->sc_mode);
52153086Sralph 	if (error)
52253086Sralph 		return (error);
52353086Sralph 
52453086Sralph 	/* check for write protected tape */
52553086Sralph 	if ((flags & FWRITE) && sc->sc_mode.writeprot) {
52653086Sralph 		uprintf("tz%d: write protected\n", unit);
52753086Sralph 		return (EACCES);
52852130Smckusick 	}
52953086Sralph 
53053086Sralph 	/* set record length */
53153086Sralph 	switch (sc->sc_tapeid) {
53253086Sralph 	case MT_ISAR:
53353086Sralph 	case MT_ISHPDAT:
53453086Sralph 	case MT_ISVIPER1:
53553086Sralph 		sc->sc_blklen = 512;
53653086Sralph 		break;
53753086Sralph 
53853086Sralph 	case MT_ISEXABYTE:
53953086Sralph #if 0
54053086Sralph 		if (minor(dev) & TZ_FIXEDBLK)
54153086Sralph 			sc->sc_blklen = 1024;
54253086Sralph 		else
54353086Sralph 			sc->sc_blklen = st_exblklen;
54452130Smckusick #endif
54553086Sralph 		break;
54653086Sralph 
54755697Sralph 	case MT_ISPYTHON:
54853086Sralph 	case MT_ISMFOUR:
54953086Sralph 	case MT_ISTK50:
55053086Sralph 		sc->sc_blklen = 0;
55153086Sralph 		break;
55253086Sralph 
55353086Sralph 	default:
55453086Sralph 		sc->sc_blklen = (sc->sc_mode.block_size2 << 16) |
55553086Sralph 			(sc->sc_mode.block_size1 << 8) | sc->sc_mode.block_size0;
55653086Sralph 	}
55753086Sralph 
55853086Sralph 	/* save total number of blocks on tape */
55953086Sralph 	sc->sc_numblks = (sc->sc_mode.blocks_2 << 16) |
56053086Sralph 		(sc->sc_mode.blocks_1 << 8) | sc->sc_mode.blocks_0;
56153086Sralph 
56253086Sralph 	/* setup for mode select */
56353086Sralph 	sc->sc_mode.len = 0;
56453086Sralph 	sc->sc_mode.media = 0;
56553086Sralph 	sc->sc_mode.bufferedMode = 1;
56653086Sralph 	sc->sc_mode.blocks_0 = 0;
56753086Sralph 	sc->sc_mode.blocks_1 = 0;
56853086Sralph 	sc->sc_mode.blocks_2 = 0;
56953086Sralph 	sc->sc_mode.block_size0 = sc->sc_blklen >> 16;
57053086Sralph 	sc->sc_mode.block_size1 = sc->sc_blklen >> 8;
57153086Sralph 	sc->sc_mode.block_size2 = sc->sc_blklen;
57253086Sralph 
57353086Sralph 	/* check for tape density changes */
57453086Sralph 	switch (sc->sc_tapeid) {
57553086Sralph 	case MT_ISAR:
57653086Sralph 		if (minor(dev) & TZ_HIDENSITY)
57753086Sralph 			sc->sc_mode.density = 0x5;
57853086Sralph 		else {
57953086Sralph 			if (flags & FWRITE) {
58053086Sralph 				uprintf("Can only write QIC-24\n");
58153086Sralph 				return (EIO);
58253086Sralph 			}
58353086Sralph 			sc->sc_mode.density = 0x4;
58453086Sralph 		}
58553086Sralph 		break;
58653086Sralph 
58753086Sralph 	case MT_ISMT02:
58853086Sralph 		/*
58953086Sralph 		 * The tape density is set automatically when the tape
59053086Sralph 		 * is loaded. We only need to change it if we are writing.
59153086Sralph 		 */
59253086Sralph 		if (flags & FWRITE) {
59353086Sralph 			if (minor(dev) & TZ_HIDENSITY)
59453086Sralph 				sc->sc_mode.density = 0;
59553086Sralph 			else
59653086Sralph 				sc->sc_mode.density = 0x4;
59753086Sralph 		}
59853086Sralph 		break;
59953086Sralph 
60053086Sralph 	case MT_ISEXABYTE:
60153086Sralph #if 0
60253086Sralph 		if (minor(dev) & TZ_HIDENSITY)
60353086Sralph 			uprintf("EXB-8200 density support only\n");
60453086Sralph 		sc->sc_mode.vupb = (u_char)st_exvup;
60553086Sralph 		sc->sc_mode.rsvd5 = 0;
60653086Sralph 		sc->sc_mode.p5 = 0;
60753086Sralph 		sc->sc_mode.motionthres = (u_char)st_exmotthr;
60853086Sralph 		sc->sc_mode.reconthres = (u_char)st_exreconthr;
60953086Sralph 		sc->sc_mode.gapthres = (u_char)st_exgapthr;
61053086Sralph #endif
61153086Sralph 		break;
61253086Sralph 
61353086Sralph 	case MT_ISHPDAT:
61453086Sralph 	case MT_ISVIPER1:
61553086Sralph 	case MT_ISPYTHON:
61653086Sralph 	case MT_ISTK50:
61753086Sralph 		if (minor(dev) & TZ_HIDENSITY)
61853086Sralph 			uprintf("tz%d: Only one density supported\n", unit);
61953086Sralph 		break;
62053086Sralph 
62153086Sralph 	case MT_ISMFOUR:
62253086Sralph 		break;		/* XXX could do density select? */
62353086Sralph 	}
62453086Sralph 
62553086Sralph 	/* set the current mode settings */
62653086Sralph 	error = tzcommand(dev, SCSI_MODE_SELECT, 0,
62753086Sralph 		sc->sc_modelen, (caddr_t)&sc->sc_mode);
62853086Sralph 	if (error)
62953086Sralph 		return (error);
63053086Sralph 
63153086Sralph 	sc->sc_ctty = tprintf_open(p);
63252130Smckusick 	sc->sc_flags = TZF_ALIVE | TZF_OPEN;
63352130Smckusick 	return (0);
63452130Smckusick }
63552130Smckusick 
tzclose(dev,flag)63652130Smckusick tzclose(dev, flag)
63752130Smckusick 	dev_t dev;
63852130Smckusick 	int flag;
63952130Smckusick {
64052130Smckusick 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
64153086Sralph 	int error = 0;
64252130Smckusick 
64352130Smckusick 	if (!(sc->sc_flags & TZF_OPEN))
64452130Smckusick 		return (0);
64552130Smckusick 	if (flag == FWRITE ||
64652130Smckusick 	    ((flag & FWRITE) && (sc->sc_flags & TZF_WRITTEN))) {
64753086Sralph 		error = tzcommand(dev, SCSI_WRITE_EOF, 0, 1, 0);
64853086Sralph #if 0
64953086Sralph 		/*
65053086Sralph 		 * Cartridge tapes don't do double EOFs on EOT.
65153086Sralph 		 */
65253086Sralph 		switch (sc->sc_tapeid) {
65353086Sralph 		case MT_ISAR:
65453086Sralph 		case MT_ISMT02:
65553086Sralph 			break;
65653086Sralph 
65753086Sralph 		default:
65853086Sralph 			error = tzcommand(dev, SCSI_WRITE_EOF, 0, 1, 0);
65953086Sralph 			if (minor(dev) & TZ_NOREWIND)
66053086Sralph 				(void) tzcommand(dev, SCSI_SPACE, 0, -1, 0);
66153086Sralph 		}
66253086Sralph #endif
66352130Smckusick 	}
66452130Smckusick 	if ((minor(dev) & TZ_NOREWIND) == 0)
66553086Sralph 		(void) tzcommand(dev, SCSI_REWIND, 0, 0, 0);
66652130Smckusick 	sc->sc_flags &= ~(TZF_OPEN | TZF_WRITTEN);
66753086Sralph 	tprintf_close(sc->sc_ctty);
66853086Sralph 	return (error);
66952130Smckusick }
67052130Smckusick 
tzioctl(dev,cmd,data,flag)67152130Smckusick tzioctl(dev, cmd, data, flag)
67252130Smckusick 	dev_t dev;
673*69799Sralph 	u_long cmd;
67452130Smckusick 	caddr_t data;
67552130Smckusick 	int flag;
67652130Smckusick {
67752130Smckusick 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
67852130Smckusick 	register struct buf *bp = &sc->sc_buf;
67952130Smckusick 	struct mtop *mtop;
68052130Smckusick 	struct mtget *mtget;
68152130Smckusick 	int code, count;
68252130Smckusick 	static tzops[] = {
68352130Smckusick 		SCSI_WRITE_EOF, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE,
68452130Smckusick 		SCSI_REWIND, SCSI_REWIND, SCSI_TEST_UNIT_READY
68552130Smckusick 	};
68652130Smckusick 
68752130Smckusick 	switch (cmd) {
68852130Smckusick 
68952130Smckusick 	case MTIOCTOP:	/* tape operation */
69052130Smckusick 		mtop = (struct mtop *)data;
69152130Smckusick 		if ((unsigned)mtop->mt_op < MTREW && mtop->mt_count <= 0)
69252130Smckusick 			return (EINVAL);
69352130Smckusick 		switch (mtop->mt_op) {
69452130Smckusick 
69552130Smckusick 		case MTWEOF:
69652130Smckusick 			code = 0;
69752130Smckusick 			count = mtop->mt_count;
69852130Smckusick 			break;
69952130Smckusick 
70052130Smckusick 		case MTFSF:
70152130Smckusick 			code = 1;
70252130Smckusick 			count = mtop->mt_count;
70352130Smckusick 			break;
70452130Smckusick 
70552130Smckusick 		case MTBSF:
70652130Smckusick 			code = 1;
70752130Smckusick 			count = -mtop->mt_count;
70852130Smckusick 			break;
70952130Smckusick 
71052130Smckusick 		case MTFSR:
71152130Smckusick 			code = 0;
71253086Sralph 			count = mtop->mt_count;
71352130Smckusick 			break;
71452130Smckusick 
71552130Smckusick 		case MTBSR:
71652130Smckusick 			code = 0;
71752130Smckusick 			count = -mtop->mt_count;
71852130Smckusick 			break;
71952130Smckusick 
72052130Smckusick 		case MTREW:
72152130Smckusick 		case MTOFFL:
72252130Smckusick 		case MTNOP:
72352130Smckusick 			code = 0;
72452130Smckusick 			count = 0;
72552130Smckusick 			break;
72652130Smckusick 
72752130Smckusick 		default:
72852130Smckusick 			return (EINVAL);
72952130Smckusick 		}
73053086Sralph 		return (tzcommand(dev, tzops[mtop->mt_op], code, count, 0));
73152130Smckusick 
73252130Smckusick 	case MTIOCGET:
73352130Smckusick 		mtget = (struct mtget *)data;
73452130Smckusick 		mtget->mt_dsreg = 0;
73552130Smckusick 		mtget->mt_erreg = sc->sc_sense.status;
73652130Smckusick 		mtget->mt_resid = 0;
73752130Smckusick 		mtget->mt_type = 0;
73852130Smckusick 		break;
73952130Smckusick 
74052130Smckusick 	default:
74152130Smckusick 		return (EINVAL);
74252130Smckusick 	}
74352130Smckusick 	return (0);
74452130Smckusick }
74552130Smckusick 
74652130Smckusick void
tzstrategy(bp)74752130Smckusick tzstrategy(bp)
74852130Smckusick 	register struct buf *bp;
74952130Smckusick {
75052130Smckusick 	register int unit = tzunit(bp->b_dev);
75152130Smckusick 	register struct tz_softc *sc = &tz_softc[unit];
75252130Smckusick 	register struct buf *dp;
75352130Smckusick 	register int s;
75452130Smckusick 
75553086Sralph 	if (sc->sc_flags & TZF_SEENEOF) {
75653086Sralph 		bp->b_resid = bp->b_bcount;
75753086Sralph 		biodone(bp);
75853086Sralph 		return;
75953086Sralph 	}
76056630Sralph 	bp->b_actf = NULL;
76152130Smckusick 	dp = &sc->sc_tab;
76252130Smckusick 	s = splbio();
76356630Sralph 	bp->b_actb = dp->b_actb;
76456630Sralph 	*dp->b_actb = bp;
76556630Sralph 	dp->b_actb = &bp->b_actf;
76652130Smckusick 	if (dp->b_active == 0) {
76752130Smckusick 		dp->b_active = 1;
76852130Smckusick 		tzstart(unit);
76952130Smckusick 	}
77052130Smckusick 	splx(s);
77152130Smckusick }
77252130Smckusick #endif
773