if (UNIT(dev) > st_cd.cd_ndevs ||
if (UNIT(dev) >= st_cd.cd_ndevs ||
stopen(dev, flag, type, p)	dev_t dev;	int flag, type;	struct proc *p;{	struct st_softc *sc;	struct st_xsense *xsense;	int count;	int stat;	int ctlr, slave, unit;	struct mode_select_data msd;	struct mode_sense mode;	int modlen;	int error;	static struct scsi_fmt_cdb modsel = {		6,		{ CMD_MODE_SELECT, 0, 0, 0, sizeof(msd), 0 }	};	static struct scsi_fmt_cdb modsense = {		6,		{ CMD_MODE_SENSE, 0, 0, 0, sizeof(mode), 0 }	};	if (UNIT(dev) > st_cd.cd_ndevs ||	    (sc = st_cd.cd_devs[UNIT(dev)]) == NULL ||	    (sc->sc_flags & STF_ALIVE) == 0)		return (ENXIO);	if (sc->sc_flags & STF_OPEN)		return (EBUSY);	ctlr = sc->sc_dev.dv_parent->dv_unit;	slave = sc->sc_target;	unit = sc->sc_lun;	xsense = &sc->sc_sense;	/*	 * Be prepared to print error messages	 */	sc->sc_ctty = tprintf_open(p);	/* do a mode sense to get current */	modlen = sc->sc_datalen[CMD_MODE_SENSE];	modsense.cdb[4] = modlen;	stat = scsi_immed_command(ctlr, slave, unit, &modsense,				  (u_char *)&mode, modlen, B_READ);	/* do a mode sense to get current */	modlen = sc->sc_datalen[CMD_MODE_SENSE];	modsense.cdb[4] = modlen;	stat = scsi_immed_command(ctlr, slave, unit, &modsense,				  (u_char *)&mode, modlen, B_READ);	/* set record length */	switch (sc->sc_tapeid) {	case MT_ISAR:		sc->sc_blklen = 512;		break;	case MT_ISEXABYTE:		if (minor(dev) & STDEV_FIXEDBLK)			sc->sc_blklen = 0x400;		else			sc->sc_blklen = st_exblklen;		break;	case MT_ISHPDAT:		sc->sc_blklen = 512;		break;	case MT_ISVIPER1:		sc->sc_blklen = 512;		break;	case MT_ISPYTHON:		sc->sc_blklen = 512;		break;	case MT_ISMFOUR:		sc->sc_blklen = 0;		break;	default:		if ((mode.md.blklen2 << 16 |		     mode.md.blklen1 << 8 |		     mode.md.blklen0) != 0)			sc->sc_blklen = mode.md.blklen2 << 16 |					mode.md.blklen1 << 8 |					mode.md.blklen0;		else			sc->sc_blklen = 512;	}	/* setup for mode select */	msd.rsvd1 = 0;	msd.rsvd2 = 0;	msd.rsvd3 = 0;	msd.buff = 1;	msd.speed = 0;	msd.blkdeslen = 0x08;	msd.density = 0;	msd.blks2 = 0;	msd.blks1 = 0;	msd.blks0 = 0;	msd.rsvd4 = 0;	msd.blklen2 = (sc->sc_blklen >> 16) & 0xff;	msd.blklen1 = (sc->sc_blklen >> 8) & 0xff;	msd.blklen0 = sc->sc_blklen & 0xff;	/*	 * Do we have any density problems?	 */	switch (sc->sc_tapeid) {	case MT_ISAR:		if (minor(dev) & STDEV_HIDENSITY)			msd.density = 0x5;		else {			if (flag & FWRITE) {				uprintf("Can only write QIC-24\n");				return(EIO);			}			msd.density = 0x4;		}		break;	case MT_ISEXABYTE:		if (minor(dev) & STDEV_HIDENSITY)			uprintf("EXB-8200 density support only\n");		msd.vupb = (u_char)st_exvup;		msd.rsvd5 = 0;		msd.p5 = 0;		msd.motionthres = (u_char)st_exmotthr;		msd.reconthres = (u_char)st_exreconthr;		msd.gapthres = (u_char)st_exgapthr;		break;	case MT_ISHPDAT:	case MT_ISVIPER1:	case MT_ISPYTHON:		if (minor(dev) & STDEV_HIDENSITY)			uprintf("Only one density supported\n");		break;	case MT_ISMFOUR:		break;		/* XXX could do density select? */	default:		uprintf("Unsupported drive\n");		return(EIO);	}	modlen = sc->sc_datalen[CMD_MODE_SELECT];	modsel.cdb[4] = modlen;	/* mode select */	count = 0;retryselect:	stat = scsi_immed_command(ctlr, slave, unit, &modsel,				  (u_char *)&msd, modlen, B_WRITE);	/*	 * First command after power cycle, bus reset or tape change 	 * will error. Try command again	 */	if (stat == STS_CHECKCOND) {		sc->sc_filepos = 0;		stxsense(ctlr, slave, unit, sc);		stat = scsi_immed_command(ctlr, slave, unit, &modsel,					  (u_char *)&msd, modlen, B_WRITE);#ifdef DEBUG		if (stat && (st_debug & ST_OPEN))			printf("stopen: stat on mode select 0x%x second try\n", stat);#endif		if (stat == STS_CHECKCOND) {			stxsense(ctlr, slave, unit, sc);			prtkey(sc);		}		if (stat)			return(EIO);	}	if (stat == -1 || stat == STS_BUSY) {		/*		 * XXX it might just be that the bus is busy because		 * another tape is doing a command. This would change		 * with connect/disconnect, ie. the other drive would		 * not hold onto the bus.		 *		 * Sleep on lbolt for up to 20 minutes (max time to FSF		 * an exabyte to EOT: 16:xx minutes)		 */		if (++count > 60*20) {			uprintf("SCSI bus timeout\n");			return(EBUSY);		}		if ((error = tsleep((caddr_t)&lbolt, PZERO | PCATCH, 		    "st_scsiwait", 0)))			return (error);		goto retryselect;	}	/* drive ready ? */	stat = scsi_test_unit_rdy(ctlr, slave, unit);	if (stat == STS_CHECKCOND) {		stxsense(ctlr, slave, unit, sc);		switch (sc->sc_tapeid) {		case MT_ISEXABYTE:			if ((xsense->sc_xsense.key & XSK_NOTRDY) &&			    xsense->exb_xsense.tnp)				uprintf("no cartridge\n");			else if (xsense->sc_xsense.key & XSK_NOTRDY)				uprintf("cartridge not loaded\n");			else if (xsense->sc_xsense.key & XSK_UNTATTEN) {				uprintf("new cart/power interrupt\n");				stat = 0;			} else if ((xsense->sc_xsense.key & XSK_UNTATTEN) &&				   xsense->exb_xsense.tnp)				uprintf("cartridge unloading\n");			else 				prtkey(sc);			break;		case MT_ISMFOUR:		case MT_ISAR:			if (xsense->sc_xsense.key & XSK_UNTATTEN)				stat = scsi_test_unit_rdy(ctlr, slave, unit);			if (stat == STS_CHECKCOND) {				stxsense(ctlr, slave, unit, sc);				if (xsense->sc_xsense.key)					prtkey(sc);			} else { 				sc->sc_filepos = 0; /* new tape */				stat = 0;			}			break;		case MT_ISHPDAT:		case MT_ISVIPER1:		case MT_ISPYTHON:			if (xsense->sc_xsense.key & XSK_UNTATTEN)				stat = scsi_test_unit_rdy(ctlr, slave, unit);			if (stat == STS_CHECKCOND) {				stxsense(ctlr, slave, unit, sc);				if (xsense->sc_xsense.key)					prtkey(sc);			}			break;		default:			uprintf("%s: not ready\n", sc->sc_dev.dv_xname);			prtkey(sc);			break;		}	}	if (stat)		return(EIO);	/* mode sense */	modlen = sc->sc_datalen[CMD_MODE_SENSE];	modsense.cdb[4] = modlen;	stat = scsi_immed_command(ctlr, slave, unit, &modsense,				  (u_char *)&mode, modlen, B_READ);#ifdef DEBUG	if (st_debug & ST_OPENSTAT)		prtmodstat(&mode);#endif	if (stat == STS_CHECKCOND) {		stxsense(ctlr, slave, unit, sc);#ifdef DEBUG		if (st_debug & ST_OPEN)			dumpxsense(xsense);#endif	}	if (stat)		return(EIO);	if ((flag & FWRITE) && mode.md.wp) {		uprintf("st:%d write protected\n", UNIT(dev));		return(EACCES);	}	/* save total number of blocks on tape */	sc->sc_numblks = mode.md.numblk2 << 16 |			 mode.md.numblk1 << 8 |			 mode.md.numblk0;	if (xsense->sc_xsense.eom && !(sc->sc_flags & STF_LEOT))		sc->sc_filepos = 0;#ifdef DEBUG	if (st_debug & ST_FMKS)		printf("%s: open filepos = %d\n", sc->sc_dev.dv_xname,		    sc->sc_filepos);#endif	sc->sc_flags |= (STF_OPEN);	if (flag & FWRITE)		sc->sc_flags |= STF_WMODE;	sc->sc_flags &= ~STF_MOVED;#ifdef TTI	/* make stats available, also lit up TTi display */	sc->sc_tticntdwn = 100;#endif	stxsense(ctlr, slave, unit, sc);	return(0);}