⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 st.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	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(UNIT(dev), 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(UNIT(dev), 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(UNIT(dev), 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(UNIT(dev), sc);			}			break;		default:			uprintf("st%d: not ready\n", UNIT(dev));			prtkey(UNIT(dev), 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("st%d: open filepos = %d\n", UNIT(dev), 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);}/*ARGSUSED*/stclose(dev, flag)	dev_t dev;	int flag;{	register struct st_softc *sc = &st_softc[UNIT(dev)];	register int hit = 0;	if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {		/*		 * Cartridge tapes don't do double EOFs on EOT.		 * We assume that variable-block devices use double EOF.		 */		stcommand(dev, MTWEOF, 1); 		if (sc->sc_blklen == 0) {			stcommand(dev, MTWEOF, 1); 			stcommand(dev, MTBSR, 1); 		}		hit++;	}	if ((minor(dev) & STDEV_NOREWIND) == 0) {		stcommand(dev, MTREW, 1);		hit++;	}#ifdef NOTDEF	/* wait until more stable before trying [XXX Needed ?] */	if (!hit && (sc->sc_flags & SFT_WMODE))		/* force out any any bufferd write data */		stcommand(dev, MTFSR, 0); #endif	/* make stats available */	stxsense(sc->sc_dq.dq_ctlr, sc->sc_dq.dq_slave, sc->sc_punit, sc);	sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN);	tprintf_close(sc->sc_ctty);	return(0);	/* XXX */}ststrategy(bp)	register struct buf *bp;{	struct buf *dp;	int unit, s;	unit = UNIT(bp->b_dev);	dp = &sttab[unit];	bp->b_actf = NULL;	s = splbio();	bp->b_actb = dp->b_actb;	*dp->b_actb = bp;	dp->b_actb = &bp->b_actf;	if (dp->b_active == 0) {		dp->b_active = 1;		stustart(unit);	}	splx(s);}stustart(unit)	int unit;{	if (scsireq(&st_softc[unit].sc_dq))		ststart(unit);}ststart(unit)	int unit;{	struct hp_device *hp = st_softc[unit].sc_hd;	if (scsiustart(hp->hp_ctlr))		stgo(unit);}stgo(unit)	int unit;{	register struct st_softc *sc = &st_softc[unit];	register struct scsi_fmt_cdb *cmd;	register struct buf *bp = sttab[unit].b_actf;	struct hp_device *hp = sc->sc_hd;	int pad, stat;	long nblks;	if (sc->sc_flags & STF_CMD) {		cmd = &stcmd[unit];		pad = 0;	} else {		cmd = bp->b_flags & B_READ ? &st_read_cmd : &st_write_cmd;		if (sc->sc_blklen)			cmd->cdb[1] |= 0x01; /* fixed mode */		else			cmd->cdb[1] &= 0xfe;		if (bp->b_flags & B_READ)			sc->sc_flags &= ~STF_WRTTN;		else			sc->sc_flags |= STF_WRTTN;		if (sc->sc_blklen) { /* fixed mode */			nblks = bp->b_bcount / sc->sc_blklen;			if (bp->b_bcount % sc->sc_blklen) {				tprintf(sc->sc_ctty,					"st%d: I/O not block aligned %d/%ld\n",					unit, sc->sc_blklen, bp->b_bcount);				cmd->cdb[1] &= 0xfe; /* force error */			}		} else	/* variable len */			nblks = bp->b_bcount;		*(u_char *)(&cmd->cdb[2]) = (u_char) (nblks >> 16);		*(u_char *)(&cmd->cdb[3]) = (u_char) (nblks >> 8);		*(u_char *)(&cmd->cdb[4]) = (u_char) nblks;		/*		 * Always Zero. We are either writing in variable		 * length mode we are writing in fixed block mode,		 * or we are going to do odd length IO and are not		 * going to use DMA.		 */		pad = 0; 	}#ifdef DEBUG	if (st_debug & ST_GO)		printf("stgo: cmd len %d [0]0x%x [1]0x%x [2]0x%x [3]0x%x [4]0x%x [5]0x%x\n",		       cmd->len, cmd->cdb[0], cmd->cdb[1], cmd->cdb[2],		       cmd->cdb[3], cmd->cdb[4], cmd->cdb[5]);#endif	sc->sc_flags |= STF_MOVED;	if (bp->b_bcount & 1) {#ifdef DEBUG		if (st_debug & ST_ODDIO)			printf("stgo%d: odd count %d using manual transfer\n",			       unit, bp->b_bcount);#endif		stat = scsi_tt_oddio(hp->hp_ctlr, hp->hp_slave, sc->sc_punit,				     bp->b_un.b_addr, bp->b_bcount,				     bp->b_flags, 1);		if (stat == 0) {			bp->b_resid = 0;			stfinish(unit, sc, bp);		}	} else		stat = scsigo(hp->hp_ctlr, hp->hp_slave, sc->sc_punit,			      bp, cmd, pad);	if (stat) {		bp->b_error = EIO;		bp->b_flags |= B_ERROR;		stxsense(sc->sc_dq.dq_ctlr, sc->sc_dq.dq_slave, 			 sc->sc_punit, sc);		sterror(unit, sc, stat);		stfinish(unit, sc, bp);	}}stfinish(unit, sc, bp)	int unit;	struct st_softc *sc;	struct buf *bp;{	register struct buf *dp;	sttab[unit].b_errcnt = 0;	if (dp = bp->b_actf)		dp->b_actb = bp->b_actb;	else		sttab[unit].b_actb = bp->b_actb;	*bp->b_actb = dp;	iodone(bp);	scsifree(&sc->sc_dq);	if (sttab[unit].b_actf)		stustart(unit);	else		sttab[unit].b_active = 0;}stread(dev, uio)	dev_t dev;	struct uio *uio;{	int unit = UNIT(dev);	return(physio(ststrategy, &stbuf[unit], dev, B_READ, minphys, uio));}stwrite(dev, uio)	dev_t dev;	struct uio *uio;{	int unit = UNIT(dev);	return(physio(ststrategy, &stbuf[unit], dev, B_WRITE, minphys, uio));}/*ARGSUSED*/stdump(dev)	dev_t dev;{	return(ENXIO);}/*ARGSUSED*/stioctl(dev, cmd, data, flag)	dev_t dev;	int cmd;	caddr_t data; 	int flag;{	register struct st_softc *sc = &st_softc[UNIT(dev)];	register int cnt;	register struct mtget *mtget;	register struct st_xsense *xp = &st_xsense[UNIT(dev)];	register struct mtop *op;	long resid;	switch (cmd) {	/* tape operation */	case MTIOCTOP:		op = (struct mtop *)data;		switch (op->mt_op) {		case MTBSR:		case MTFSR:			if (sc->sc_tapeid == MT_ISAR)				return(ENXIO);		case MTWEOF:		case MTFSF:		case MTBSF:			cnt = (int)op->mt_count;			break;		case MTREW:		case MTOFFL:			cnt = 1;			break;		case MTNOP:			return(0);		default:			return(EINVAL);		}		if (cnt <= 0)			return(EINVAL);		stcommand(dev, (u_int)op->mt_op, cnt);		break;	/* drive status */	case MTIOCGET:		mtget = (struct mtget *)data;		stxsense(sc->sc_dq.dq_ctlr, sc->sc_dq.dq_slave, 			 sc->sc_punit, sc);		mtget->mt_type = sc->sc_tapeid;		mtget->mt_dsreg = 0;		mtget->mt_erreg = ((xp->sc_xsense.valid << 15) |				   (xp->sc_xsense.filemark << 14) |				   (xp->sc_xsense.eom << 13) |				   (xp->sc_xsense.ili << 12) |				   (xp->sc_xsense.key << 8));				if (sc->sc_tapeid == MT_ISEXABYTE) {			mtget->mt_dsreg = sc->sc_flags;			resid = (xp->exb_xsense.tplft2 << 16 |				 xp->exb_xsense.tplft1 << 8 |				 xp->exb_xsense.tplft0);			mtget->mt_resid = resid / 1000;			mtget->mt_erreg |= (((xp->exb_xsense.rwerrcnt2 << 16 |					      xp->exb_xsense.rwerrcnt1 << 8 |					      xp->exb_xsense.rwerrcnt0) * 100) / 					    (sc->sc_numblks - resid)) & 0xff;		} else if (xp->sc_xsense.valid) {			resid = ((xp->sc_xsense.info1 << 24) |				 (xp->sc_xsense.info2 << 16) |				 (xp->sc_xsense.info3 << 8) |				 (xp->sc_xsense.info4));			if (sc->sc_blklen) /* if fixed mode */				resid *= sc->sc_blklen;			mtget->mt_resid = resid;		} else			mtget->mt_resid = 0;		break;	default:		return(ENXIO);	}	return(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -