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

📄 tz.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
				 * end of record.				 * Fixed length blocks, an error.				 */				if (sp->endOfMedia) {					bp->b_error = ENOSPC;					bp->b_resid = resid;					break;				}				if (sc->sc_blklen && sp->badBlockLen) {					tprintf(sc->sc_ctty,						"tz%d: Incorrect Block Length, expected %d got %d\n",						unit, sc->sc_blklen, resid);					break;				}				if (resid < 0) {					/*					 * Variable length records but					 * attempted to read less than a					 * full record.					 */					tprintf(sc->sc_ctty,						"tz%d: Partial Read of Variable Length Tape Block, expected %d read %d\n",						unit, bp->b_bcount - resid,						bp->b_bcount);					bp->b_resid = 0;					break;				}				if (sp->fileMark)					sc->sc_flags |= TZF_SEENEOF;				/*				 * Attempting to read more than a record is				 * OK. Just record how much was actually read.				 */				bp->b_flags &= ~B_ERROR;				bp->b_error = 0;				bp->b_resid = resid;				break;			case SCSI_CLASS7_UNIT_ATTN:				if (!(sc->sc_flags & TZF_OPEN))					break;			default:			prerr:				printf("tz%d: ", unit);				scsiPrintSense((ScsiClass7Sense *)					sc->sc_sense.sense,					sizeof(sc->sc_sense.sense) - resid);			}		}	} else if (error || (status & SCSI_STATUS_CHECKCOND)) {#ifdef DEBUG		if (!cold && tzdebug)			printf("tz%d: error %d scsi status 0x%x\n",				unit, error, status);#endif		/* save error info */		sc->sc_sense.status = status;		bp->b_flags |= B_ERROR;		bp->b_error = error;		bp->b_resid = resid;		if (status & SCSI_STATUS_CHECKCOND) {			/*			 * Start a REQUEST_SENSE command.			 * Since we are called at interrupt time, we can't			 * wait for the command to finish; that's why we use			 * the sc_flags field.			 */			sc->sc_flags |= TZF_SENSEINPROGRESS;			sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);			scsiGroup0Cmd(SCSI_REQUEST_SENSE, sc->sc_sd->sd_slave,				0, sizeof(sc->sc_sense.sense),				(ScsiGroup0Cmd *)sc->sc_cdb.cdb);			sc->sc_errbuf.b_flags = B_BUSY | B_PHYS | B_READ;			sc->sc_errbuf.b_bcount = sizeof(sc->sc_sense.sense);			sc->sc_errbuf.b_un.b_addr = (caddr_t)sc->sc_sense.sense;			sc->sc_errbuf.b_actf = bp;			sc->sc_errbuf.b_actb = bp->b_actb;			*bp->b_actb = &sc->sc_errbuf;			bp->b_actb = &sc->sc_errbuf.b_actf;			tzstart(unit);			return;		}	} else {		sc->sc_sense.status = status;		bp->b_resid = resid;	}	if (dp = bp->b_actf)		dp->b_actb = bp->b_actb;	else		sc->sc_tab.b_actb = bp->b_actb;	*bp->b_actb = dp;	biodone(bp);	if (sc->sc_tab.b_actf)		tzstart(unit);	else {		sc->sc_tab.b_active = 0;		if (sc->sc_flags & TZF_WAIT) {			sc->sc_flags &= ~TZF_WAIT;			wakeup(&sc->sc_flags);		}	}}/* ARGSUSED */tzopen(dev, flags, type, p)	dev_t dev;	int flags, type;	struct proc *p;{	register int unit = tzunit(dev);	register struct tz_softc *sc = &tz_softc[unit];	int error;	if (unit >= NTZ || sc->sc_sd == NULL)		return (ENXIO);	if (!(sc->sc_flags & TZF_ALIVE)) {		/* check again, tape may have been turned off at boot time */		if (!tzprobe(sc->sc_sd))			return (ENXIO);	}	if (sc->sc_flags & TZF_OPEN)		return (EBUSY);	/* clear UNIT_ATTENTION */	error = tzcommand(dev, SCSI_TEST_UNIT_READY, 0, 0, 0);	while (error) {		ScsiClass7Sense *sp = (ScsiClass7Sense *)sc->sc_sense.sense;		/* return error if last error was not UNIT_ATTENTION */		if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND) ||		    sp->error7 != 0x70 || sp->key != SCSI_CLASS7_UNIT_ATTN)			return (error);		/*		 * Try it again just to be sure and		 * try to negotiate synchonous transfers.		 */		error = tzcommand(dev, SCSI_TEST_UNIT_READY, 0, 0, 0);	}	/* get the current mode settings */	error = tzcommand(dev, SCSI_MODE_SENSE, 0,		sc->sc_modelen, (caddr_t)&sc->sc_mode);	if (error)		return (error);	/* check for write protected tape */	if ((flags & FWRITE) && sc->sc_mode.writeprot) {		uprintf("tz%d: write protected\n", unit);		return (EACCES);	}	/* set record length */	switch (sc->sc_tapeid) {	case MT_ISAR:	case MT_ISHPDAT:	case MT_ISVIPER1:		sc->sc_blklen = 512;		break;	case MT_ISEXABYTE:#if 0		if (minor(dev) & TZ_FIXEDBLK)			sc->sc_blklen = 1024;		else			sc->sc_blklen = st_exblklen;#endif		break;	case MT_ISPYTHON:	case MT_ISMFOUR:	case MT_ISTK50:		sc->sc_blklen = 0;		break;	default:		sc->sc_blklen = (sc->sc_mode.block_size2 << 16) |			(sc->sc_mode.block_size1 << 8) | sc->sc_mode.block_size0;	}	/* save total number of blocks on tape */	sc->sc_numblks = (sc->sc_mode.blocks_2 << 16) |		(sc->sc_mode.blocks_1 << 8) | sc->sc_mode.blocks_0;	/* setup for mode select */	sc->sc_mode.len = 0;	sc->sc_mode.media = 0;	sc->sc_mode.bufferedMode = 1;	sc->sc_mode.blocks_0 = 0;	sc->sc_mode.blocks_1 = 0;	sc->sc_mode.blocks_2 = 0;	sc->sc_mode.block_size0 = sc->sc_blklen >> 16;	sc->sc_mode.block_size1 = sc->sc_blklen >> 8;	sc->sc_mode.block_size2 = sc->sc_blklen;	/* check for tape density changes */	switch (sc->sc_tapeid) {	case MT_ISAR:		if (minor(dev) & TZ_HIDENSITY)			sc->sc_mode.density = 0x5;		else {			if (flags & FWRITE) {				uprintf("Can only write QIC-24\n");				return (EIO);			}			sc->sc_mode.density = 0x4;		}		break;	case MT_ISMT02:		/*		 * The tape density is set automatically when the tape		 * is loaded. We only need to change it if we are writing.		 */		if (flags & FWRITE) {			if (minor(dev) & TZ_HIDENSITY)				sc->sc_mode.density = 0;			else				sc->sc_mode.density = 0x4;		}		break;	case MT_ISEXABYTE:#if 0		if (minor(dev) & TZ_HIDENSITY)			uprintf("EXB-8200 density support only\n");		sc->sc_mode.vupb = (u_char)st_exvup;		sc->sc_mode.rsvd5 = 0;		sc->sc_mode.p5 = 0;		sc->sc_mode.motionthres = (u_char)st_exmotthr;		sc->sc_mode.reconthres = (u_char)st_exreconthr;		sc->sc_mode.gapthres = (u_char)st_exgapthr;#endif		break;	case MT_ISHPDAT:	case MT_ISVIPER1:	case MT_ISPYTHON:	case MT_ISTK50:		if (minor(dev) & TZ_HIDENSITY)			uprintf("tz%d: Only one density supported\n", unit);		break;	case MT_ISMFOUR:		break;		/* XXX could do density select? */	}	/* set the current mode settings */	error = tzcommand(dev, SCSI_MODE_SELECT, 0,		sc->sc_modelen, (caddr_t)&sc->sc_mode);	if (error)		return (error);	sc->sc_ctty = tprintf_open(p);	sc->sc_flags = TZF_ALIVE | TZF_OPEN;	return (0);}tzclose(dev, flag)	dev_t dev;	int flag;{	register struct tz_softc *sc = &tz_softc[tzunit(dev)];	int error = 0;	if (!(sc->sc_flags & TZF_OPEN))		return (0);	if (flag == FWRITE ||	    ((flag & FWRITE) && (sc->sc_flags & TZF_WRITTEN))) {		error = tzcommand(dev, SCSI_WRITE_EOF, 0, 1, 0);#if 0		/*		 * Cartridge tapes don't do double EOFs on EOT.		 */		switch (sc->sc_tapeid) {		case MT_ISAR:		case MT_ISMT02:			break;		default:			error = tzcommand(dev, SCSI_WRITE_EOF, 0, 1, 0);			if (minor(dev) & TZ_NOREWIND)				(void) tzcommand(dev, SCSI_SPACE, 0, -1, 0);		}#endif	}	if ((minor(dev) & TZ_NOREWIND) == 0)		(void) tzcommand(dev, SCSI_REWIND, 0, 0, 0);	sc->sc_flags &= ~(TZF_OPEN | TZF_WRITTEN);	tprintf_close(sc->sc_ctty);	return (error);}tzioctl(dev, cmd, data, flag)	dev_t dev;	int cmd;	caddr_t data;	int flag;{	register struct tz_softc *sc = &tz_softc[tzunit(dev)];	register struct buf *bp = &sc->sc_buf;	struct mtop *mtop;	struct mtget *mtget;	int code, count;	static tzops[] = {		SCSI_WRITE_EOF, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE,		SCSI_REWIND, SCSI_REWIND, SCSI_TEST_UNIT_READY	};	switch (cmd) {	case MTIOCTOP:	/* tape operation */		mtop = (struct mtop *)data;		if ((unsigned)mtop->mt_op < MTREW && mtop->mt_count <= 0)			return (EINVAL);		switch (mtop->mt_op) {		case MTWEOF:			code = 0;			count = mtop->mt_count;			break;		case MTFSF:			code = 1;			count = mtop->mt_count;			break;		case MTBSF:			code = 1;			count = -mtop->mt_count;			break;		case MTFSR:			code = 0;			count = mtop->mt_count;			break;		case MTBSR:			code = 0;			count = -mtop->mt_count;			break;		case MTREW:		case MTOFFL:		case MTNOP:			code = 0;			count = 0;			break;		default:			return (EINVAL);		}		return (tzcommand(dev, tzops[mtop->mt_op], code, count, 0));	case MTIOCGET:		mtget = (struct mtget *)data;		mtget->mt_dsreg = 0;		mtget->mt_erreg = sc->sc_sense.status;		mtget->mt_resid = 0;		mtget->mt_type = 0;		break;	default:		return (EINVAL);	}	return (0);}voidtzstrategy(bp)	register struct buf *bp;{	register int unit = tzunit(bp->b_dev);	register struct tz_softc *sc = &tz_softc[unit];	register struct buf *dp;	register int s;	if (sc->sc_flags & TZF_SEENEOF) {		bp->b_resid = bp->b_bcount;		biodone(bp);		return;	}	bp->b_actf = NULL;	dp = &sc->sc_tab;	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;		tzstart(unit);	}	splx(s);}#endif

⌨️ 快捷键说明

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