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

📄 st.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		 * physical tape position may not be what we've been		 * telling the user; adjust the position accordingly		 */		if (mtop->mt_count && IN_EOF(un)) {			int blkno = un->un_blkno;			int fileno = un->un_fileno;			int lastop = un->un_lastop;			if (stcmd(devp, SCMD_SPACE, Fmk((-1)), SYNC_CMD) == -1)				return (EIO);			un->un_blkno = blkno;			un->un_fileno = fileno;			un->un_lastop = lastop;		}		if (check_density_or_wfm(dev, 1, B_READ, STEPBACK)) {			return (EIO);		}space_records:		tmp = un->un_blkno + mtop->mt_count;		if (tmp == un->un_blkno) {			un->un_err_resid = 0;			un->un_err_fileno = un->un_fileno;			un->un_err_blkno = un->un_blkno;			break;		} else if (un->un_blkno < tmp ||		    (un->un_dp->options & ST_BSR)) {			/*			 * If we're spacing forward, or the device can			 * backspace records, we can just use the SPACE			 * command.			 */			tmp = tmp - un->un_blkno;			if (stcmd(devp, SCMD_SPACE, Blk(tmp), SYNC_CMD)) {				rval = EIO;			} else if (un->un_eof >= ST_EOF_PENDING) {				/*				 * check if we hit BOT/EOT				 */				if (tmp < 0 && un->un_eof == ST_EOM) {					un->un_status = SUN_KEY_BOT;					un->un_eof = ST_NO_EOF;				} else if (tmp < 0 && un->un_eof ==				    ST_EOF_PENDING) {					int residue = un->un_err_resid;					/*					 * we skipped over a filemark					 * and need to go forward again					 */					if (stcmd(devp, SCMD_SPACE, Fmk(1),					    SYNC_CMD)) {						rval = EIO;					}					un->un_err_resid = residue;				}				if (rval == 0)					rval = EIO;			}		} else {			/*			 * else we rewind, space forward across filemarks to			 * the desired file, and then space records to the			 * desired block.			 */			int t = un->un_fileno;	/* save current file */			if (tmp < 0) {				/*				 * Wups - we're backing up over a filemark				 */				if (un->un_blkno != 0 &&				    (stcmd(devp, SCMD_REWIND, 0, SYNC_CMD) ||				    stcmd(devp, SCMD_SPACE, Fmk(t), SYNC_CMD)))					un->un_fileno = -1;				un->un_err_resid = -tmp;				if (un->un_fileno == 0 && un->un_blkno == 0) {					un->un_status = SUN_KEY_BOT;					un->un_eof = ST_NO_EOF;				} else if (un->un_fileno > 0) {					un->un_status = SUN_KEY_EOF;					un->un_eof = ST_NO_EOF;				}				un->un_err_fileno = un->un_fileno;				un->un_err_blkno = un->un_blkno;				rval = EIO;			} else if (stcmd(devp, SCMD_REWIND, 0, SYNC_CMD) ||				    stcmd(devp, SCMD_SPACE, Fmk(t), SYNC_CMD) ||				    stcmd(devp, SCMD_SPACE, Blk(tmp), SYNC_CMD))			{				un->un_fileno = -1;				rval = EIO;			}		}		break;	case MTBSF:		/*		 * backward space of file filemark (1/2" and 8mm)		 * tape position will end on the beginning of tape side		 * of the desired file mark		 */		if ((un->un_dp->options & ST_BSF) == 0) {			return (ENOTTY);		}		/*		 * If a negative count (which implies a forward space op)		 * is specified, and we're at logical or physical eot,		 * bounce the request.		 */		if (un->un_eof >= ST_EOT && mtop->mt_count < 0) {			un->un_err_resid = mtop->mt_count;			un->un_status = SUN_KEY_EOT;			return (EIO);		}		/*		 * physical tape position may not be what we've been		 * telling the user; adjust the request accordingly		 */		if (mtop->mt_count && IN_EOF(un)) {			un->un_fileno++;			un->un_blkno = 0;			if (mtop->mt_count < 0) {				mtop->mt_count--;			} else if (mtop->mt_count == 0) {				/*				 * For all cases here, this means move				 * to block zero of the current (physical)				 * file.				 */				mtop->mt_count = 1;				mtop->mt_op = MTNBSF;				goto mtnbsf;			} else if (mtop->mt_count > 0) {				mtop->mt_count++;			}		}		if (check_density_or_wfm(dev, 1, 0, STEPBACK)) {			return (EIO);		}		if (mtop->mt_count <= 0) {			mtop->mt_op = MTFSF;			mtop->mt_count = -mtop->mt_count;			goto fspace;		}bspace:	{		/*		 * Backspace files (MTNBSF):		 *		 *	For tapes that can backspace, backspace		 *	count+1 filemarks and then run forward over		 *	a filemark		 *		 *	For tapes that can't backspace,		 *		calculate desired filenumber		 *		(un->un_fileno - count), rewind,		 *		and then space forward this amount		 *		 * Backspace filemarks (MTBSF)		 *		 *	For tapes that can backspace, backspace count		 *	filemarks		 *		 *	For tapes that can't backspace, calculate		 *	desired filenumber (un->un_fileno - count),		 *	add 1, rewind, space forward this amount,		 *	and mark state as ST_EOF_PENDING appropriately.		 */		int skip_cnt, end_at_eof;		if (mtop->mt_op == MTBSF)			end_at_eof = 1;		else			end_at_eof = 0;		DPRINTF_IOCTL(devp,		    "bspace: mt_op=%x, count=%x, fileno=%x, blkno=%x\n",		    mtop->mt_op, mtop->mt_count, un->un_fileno, un->un_blkno);		/*		 * Handle the simple case of BOT		 * playing a role in these cmds.		 * We do this by calculating the		 * ending file number. If the ending		 * file is < BOT, rewind and set an		 * error and mark resid appropriately.		 * If we're backspacing a file (not a		 * filemark) and the target file is		 * the first file on the tape, just		 * rewind.		 */		tmp = un->un_fileno - mtop->mt_count;		if ((end_at_eof && tmp < 0) || (end_at_eof == 0 && tmp <= 0)) {			if (stcmd (devp, SCMD_REWIND, 0, SYNC_CMD)) {				rval = EIO;			}			if (tmp < 0) {				rval = EIO;				un->un_err_resid = -tmp;				un->un_status = SUN_KEY_BOT;			}			break;		}		if (un->un_dp->options & ST_BSF) {			skip_cnt = 1 - end_at_eof;			/*			 * If we are going to end up at the beginning			 * of the file, we have to space one extra file			 * first, and then space forward later.			 */			tmp = -(mtop->mt_count + skip_cnt);			DPRINTF_IOCTL(devp, "skip_cnt=%x, tmp=%x\n",				skip_cnt, tmp);			if (stcmd(devp, SCMD_SPACE, Fmk(tmp), SYNC_CMD)) {				rval = EIO;			}		} else {			if (stcmd(devp, SCMD_REWIND, 0, SYNC_CMD)) {				rval = EIO;			} else {				skip_cnt = tmp + end_at_eof;			}		}		/*		 * If we have to space forward, do so...		 */		DPRINTF_IOCTL(devp, "space forward skip_cnt=%x, rval=%x\n",		    skip_cnt, rval);		if (rval == 0 && skip_cnt) {			if (stcmd(devp, SCMD_SPACE, Fmk(skip_cnt), SYNC_CMD)) {				rval = EIO;			} else if (end_at_eof) {				/*				 * If we had to space forward, and we're				 * not a tape that can backspace, mark state				 * as if we'd just seen a filemark during a				 * a read.				 */				if ((un->un_dp->options & ST_BSF) == 0) {					un->un_eof = ST_EOF_PENDING;					un->un_fileno -= 1;					un->un_blkno = INF;				}			}		}		if (rval)			un->un_fileno = -1;		break;	}	case MTNBSF:		/*		 * backward space file to beginning of file		 *		 * If a negative count (which implies a forward space op)		 * is specified, and we're at logical or physical eot,		 * bounce the request.		 */		if (un->un_eof >= ST_EOT && mtop->mt_count < 0) {			un->un_err_resid = mtop->mt_count;			un->un_status = SUN_KEY_EOT;			return (EIO);		}		/*		 * physical tape position may not be what we've been		 * telling the user; adjust the request accordingly		 */		if (mtop->mt_count && IN_EOF(un)) {			un->un_fileno++;			un->un_blkno = 0;			if (mtop->mt_count < 0) {				mtop->mt_count--;			} else if (mtop->mt_count == 0) {				/*				 * For all cases here, this means move				 * to block zero of the current (physical)				 * file.				 */				mtop->mt_count = 1;			} else if (mtop->mt_count > 0) {				mtop->mt_count++;			}		}		if (check_density_or_wfm(dev, 1, 0, STEPBACK)) {			return (EIO);		}mtnbsf:		if (mtop->mt_count <= 0) {			mtop->mt_op = MTFSF;			mtop->mt_count = -mtop->mt_count;			goto fspace;		}		goto bspace;	case MTBSR:		/*		 * backward space into inter-record gap		 *		 * If a negative count (which implies a forward space op)		 * is specified, and we're at logical or physical eot,		 * bounce the request.		 */		if (un->un_eof >= ST_EOT && mtop->mt_count < 0) {			un->un_err_resid = mtop->mt_count;			un->un_status = SUN_KEY_EOT;			return (EIO);		}		if (mtop->mt_count == 0) {			return (0);		}		/*		 * physical tape position may not be what we've been		 * telling the user; adjust the position accordingly.		 * bsr can not skip filemarks and continue to skip records		 * therefore if we are logically before the filemark but		 * physically at the EOT side of the filemark, we need to step		 * back; this allows fsr N where N > number of blocks in file		 * followed by bsr 1 to position at the beginning of  last block		 */		if (IN_EOF(un)) {			int blkno = un->un_blkno;			int fileno = un->un_fileno;			int lastop = un->un_lastop;			if (stcmd(devp, SCMD_SPACE, Fmk((-1)), SYNC_CMD) == -1)				return (EIO);			un->un_blkno = blkno;			un->un_fileno = fileno;			un->un_lastop = lastop;		}		un->un_eof = ST_NO_EOF;		if (check_density_or_wfm(dev, 1, 0, STEPBACK)) {			return (EIO);		}		mtop->mt_count = -mtop->mt_count;		goto space_records;	default:		rval = ENOTTY;	}	DPRINTF_IOCTL(devp,	    "stioctl: fileno=%x, blkno=%x, un_eof=%x\n", un->un_fileno,	    un->un_blkno, un->un_eof);	if (un->un_fileno < 0)		un->un_density_known = 0;	return (rval);}static intst_write_fm(dev, wfm)dev_t dev;int wfm;{	register struct scsi_device *devp;	register struct scsi_tape *un;	int i;	if ((devp = stunits[MTUNIT(dev)]) == 0)		return (ENXIO);	un = UPTR;	/*	 * write one filemark at the time after EOT	 */	if (un->un_eof >= ST_EOT) {		for (i = 0; i < wfm; i++) {			if (stcmd(devp, SCMD_WRITE_FILE_MARK, 1, SYNC_CMD)) {				return (EIO);			}		}	} else if (stcmd(devp, SCMD_WRITE_FILE_MARK, wfm, SYNC_CMD)) {				return (EIO);	}	return (0);}/* * Command start && done functions */static voidststart(devp)register struct scsi_device *devp;{	register struct buf *bp;	register struct scsi_tape *un = UPTR;	if (un->un_runq || (bp = un->un_quef) == NULL) {		return;	}	if (!BP_PKT(bp)) {		make_st_cmd(devp, bp, strunout);		if (!BP_PKT(bp)) {			un->un_state = ST_STATE_RESOURCE_WAIT;			return;		}		un->un_state = ST_STATE_OPEN;	}	un->un_runq = bp;	un->un_quef = bp->b_actf;	bp->b_actf = 0;	if (pkt_transport(BP_PKT(bp)) != TRAN_ACCEPT) {		stprintf(devp, "transport rejected");		bp->b_resid = bp->b_bcount;		bp->b_flags |= B_ERROR;		bp->b_error = EIO;		stdone(devp);	}}static intstrunout(){	register i, rval, s;	register struct scsi_device *devp;	register struct scsi_tape *un;	rval = 1;	s = splr(stpri);	for (i = 0; i < ST_MAXUNIT; i++) {		devp = stunits[i];		if (devp && devp->sd_present && (un = UPTR) &&		    un->un_attached) {			if (un->un_state == ST_STATE_RESOURCE_WAIT) {				ststart(devp);				if (un->un_state == ST_STATE_RESOURCE_WAIT) {					rval = 0;					break;				}			}		}	}	(void) splx(s);	return (rval);}static voidstdone(devp)register struct scsi_device *devp;{	register struct buf *bp;	register struct scsi_tape *un = UPTR;	bp = un->un_runq;	un->un_runq = NULL;	/*	 * Start the next one before releasing resources on this one	 */	if (un->un_quef) {		ststart(devp);	}	if (bp != un->un_sbufp) {		scsi_resfree(BP_PKT(bp));		iodone(bp);	} else {		bp->b_flags |= B_DONE;		if (bp->b_flags & B_ASYNC) {			int com;			scsi_resfree (BP_PKT(bp));			com = (int) bp->b_forw;			if (com == SCMD_READ || com == SCMD_WRITE) {				bp->b_un.b_addr = (caddr_t) 0;			}			bp->b_flags &= ~(B_BUSY|B_ASYNC);			if (bp->b_flags & B_WANTED) {				wakeup((caddr_t) bp);			}		} else {			wakeup((caddr_t) un);		}	}}/* * Utility functions */static intst_determine_generic(devp)struct scsi_device *devp;{	u_char dens;	int bsize;	struct scsi_tape *un = UPTR;	static char *cart = "0.25 inch cartridge";	char *sizestr, local[8+3];	if (stcmd(devp, SCMD_MODE_SENSE, MSIZE, SYNC_CMD))		return (-1);	bsize = (un->un_mspl->high_bl << 16)	|		(un->un_mspl->mid_bl << 8)	|		(un->un_mspl->low_bl);	if (bsize == 0) {		un->un_dp->options |= ST_VARIABLE;		un->un_dp->bsize = 10 << 10;	} else if (bsize > ST_MAXRECSIZE_FIXED) {		/*		 * record size of this device too big.		 * try and convert it to variable record length.		 *		 */		un->un_dp->options |= ST_VARIABLE;		if (st_modeselect(devp)) {			stprintf(devp, "Fixed Record Size %d is too large",			    bsize);			stprintf(devp, "Cannot switch to variable record size");			un->un_dp->options &= ~ST_VARIABLE;			return (-1);		}		un->un_mspl->high_bl = un->un_mspl->mid_bl =		    un->un_mspl->low_bl = 0;	} else {		un->un_dp->bsize = (u_short) bsize;	}	switch (dens = un->un_mspl->density) {	default:	case 0x0:		/*		 * default density, cannot determine any other		 * information.		 */		sizestr = "Unknown type- assuming 0.25 inch cartridge";		un->un_dp->type = ST_TYPE_DEFAULT;		un->un_dp->options |= (ST_AUTODEN_OVERRIDE|ST_QIC);		break;	case 0x1:	case 0x2:	case 0x3:	case 0x6:

⌨️ 快捷键说明

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