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

📄 st.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/*		 * 1/2" reel		 */		sizestr = "0.50 inch reel";		un->un_dp->type = ST_TYPE_REEL;		un->un_dp->options |= ST_REEL;		un->un_dp->densities[0] = 0x1;		un->un_dp->densities[1] = 0x2;		un->un_dp->densities[2] = 0x6;		un->un_dp->densities[3] = 0x3;		break;	case 0x4:	case 0x5:	case 0x7:	case 0x0b:		/*		 * Quarter inch.		 */		sizestr = cart;		un->un_dp->type = ST_TYPE_DEFAULT;		un->un_dp->options |= ST_QIC;		un->un_dp->densities[1] = 0x4;		un->un_dp->densities[2] = 0x5;		un->un_dp->densities[3] = 0x7;		un->un_dp->densities[0] = 0x0b;		break;	case 0x0f:	case 0x10:	case 0x11:	case 0x12:		/*		 * QIC-120, QIC-150, QIC-320, QIC-600		 */		sizestr = cart;		un->un_dp->type = ST_TYPE_DEFAULT;		un->un_dp->options |= ST_QIC;		un->un_dp->densities[0] = 0x0f;		un->un_dp->densities[1] = 0x10;		un->un_dp->densities[2] = 0x11;		un->un_dp->densities[3] = 0x12;		break;	case 0x09:	case 0x0a:	case 0x0c:	case 0x0d:		/*		 * 1/2" cartridge tapes. Include HI-TC.		 */		sizestr = cart;		sizestr[2] = '5';		sizestr[3] = '0';		un->un_dp->type = ST_TYPE_HIC;		un->un_dp->densities[0] = 0x09;		un->un_dp->densities[1] = 0x0a;		un->un_dp->densities[2] = 0x0c;		un->un_dp->densities[3] = 0x0d;		break;	case 0x13:	case 0x14:		/*		 * Helical Scan (Exabyte) devices		 */		if (dens == 0x13)			sizestr = "3.81mm helical scan cartridge";		else			sizestr = "8mm helical scan cartridge";		un->un_dp->type = ST_TYPE_EXABYTE;		un->un_dp->options |= ST_AUTODEN_OVERRIDE;		break;	}	/*	 * Assume LONG ERASE and NO BUFFERED MODE	 */	un->un_dp->options |= (ST_LONG_ERASE|ST_NOBUF);	/*	 * set up large read and write retry counts	 */	un->un_dp->max_rretries = un->un_dp->max_wretries = 1000;	/*	 * make up name	 */	local[0] = '<';	bcopy(devp->sd_inq->inq_vid, &local[1], 8);	local[9] = '>';	local[10] = 0;	/*	 * If this is a 0.50 inch reel tape, and	 * it is *not* variable mode, try and	 * set it to variable record length	 * mode.	 */	if ((un->un_dp->options & (ST_VARIABLE|ST_REEL)) == ST_REEL) {		un->un_dp->options |= ST_VARIABLE;		if (st_modeselect(devp)) {			un->un_dp->options &= ~ST_VARIABLE;		} else {			un->un_dp->bsize = 10 << 10;			un->un_mspl->high_bl = un->un_mspl->mid_bl =			    un->un_mspl->low_bl = 0;		}	}	/*	 * Write to console about type of device found	 */	stprintf(devp, "Generic Drive, Vendor=%s\n\t%s", local, sizestr);	if (un->un_dp->options & ST_VARIABLE) {		printf("\tVariable record length I/O\n");	} else {		printf("\tFixed record length (%d byte blocks) I/O\n",			un->un_dp->bsize);	}	return (0);}static intst_determine_density(devp, rw)struct scsi_device *devp;int rw;{	struct scsi_tape *un = UPTR;	/*	 * If we're past BOT, density is determined already.	 */	if (un->un_fileno > 0) {		/*		 * XXX:	put in a bitch message about attempting to		 * XXX:	change density past BOT.		 */		return (0);	}	/*	 * If we're going to be writing, we set the density	 */	if (rw == B_WRITE) {		/* un_curdens is used as an index into densities table */		un->un_curdens = MT_DENSITY(un->un_dev);		if (st_set_density(devp)) {			return (-1);		}		return (0);	}	/*	 * If density is known already,	 * we don't have to get it again.(?)	 */	if (un->un_density_known)		return (0);	if (st_get_density(devp)) {		return (-1);	}	return (0);}/* * Try to determine density. We do this by attempting to read the * first record off the tape, cycling through the available density * codes as we go. */static intst_get_density(devp)struct scsi_device *devp;{	register struct scsi_tape *un = UPTR;	int succes = 0, rval = -1, i;	u_int size;	u_char dens, olddens;	if (un->un_dp->options & ST_AUTODEN_OVERRIDE) {		un->un_density_known = 1;		return (0);	}	/*	 * This will only work on variable record length tapes	 * if and only if all variable record length tapes autodensity	 * select.	 */	size = (unsigned) un->un_dp->bsize;	un->un_tmpbuf = (caddr_t) kmem_alloc(size);	/*	 * Start at the specified density	 */	dens = olddens = un->un_curdens = MT_DENSITY(un->un_dev);	for (i = 0; i < NDENSITIES; i++, ((un->un_curdens == NDENSITIES-1) ?					un->un_curdens = 0 :					un->un_curdens += 1)) {		/*		 * If we've done this density before,		 * don't bother to do it again.		 */		dens = un->un_dp->densities[un->un_curdens];		if (i > 0 && dens == olddens)			continue;		olddens = dens;		DPRINTF(devp, "trying density 0x%x", dens);		if (st_set_density(devp))			continue;		succes = (stcmd(devp, SCMD_READ, (int) size, SYNC_CMD) == 0);		if (stcmd(devp, SCMD_REWIND, 0, SYNC_CMD)) {			break;		}		if (succes) {			stinit(un);			rval = 0;			un->un_density_known = 1;			break;		}	}	(void) kmem_free(un->un_tmpbuf, size);	un->un_tmpbuf = 0;	return (rval);}static intst_set_density(devp)struct scsi_device *devp;{	struct scsi_tape *un = UPTR;	if ((un->un_dp->options & ST_AUTODEN_OVERRIDE) == 0) {		un->un_mspl->density = un->un_dp->densities[un->un_curdens];		if (st_modeselect(devp)) {			return (-1);		}	}	un->un_density_known = 1;	return (0);}static intst_loadtape(devp)struct scsi_device *devp;{	/*	 * 'LOAD' the tape to BOT	 */	if (stcmd(devp, SCMD_LOAD, 1, SYNC_CMD)) {		/*		 * Don't bounce the loadtape function here- some devices		 * don't support the load command. For them, if the load		 * tape command fails with an ILLEGAL REQUEST sense key,		 * try a rewind instead.		 */		if (UPTR->un_status == KEY_ILLEGAL_REQUEST) {			if (stcmd(devp, SCMD_REWIND, 0, SYNC_CMD)) {				return (-1);			}		} else			return (-1);	}	/*	 * run a MODE SENSE to get the write protect status, then run	 * a MODESELECT operation in order to set any modes that might	 * be appropriate for this device (like VARIABLE, etc..)	 */	if (stcmd(devp, SCMD_MODE_SENSE, MSIZE, SYNC_CMD) ||	    st_modeselect(devp))		return (-1);	stinit(UPTR);	UPTR->un_density_known = 0;	return (0);}/* * Note: QIC devices aren't so smart.  If you try to append * after EOM, the write can fail because the device doesn't know * it's at EOM.  In that case, issue a read.  The read should fail * because there's no data, but the device knows it's at EOM, * so a subsequent write should succeed.  To further confuse matters, * the target returns the same error if the tape is positioned * such that a write would overwrite existing data.  That's why * we have to do the append test.  A read in the middle of * recorded data would succeed, thus indicating we're attempting * something illegal. */static voidst_test_append(bp)struct buf *bp;{	struct scsi_device *devp = stunits[MTUNIT(bp->b_dev)];	struct scsi_tape *un = UPTR;	int status;	DPRINTF(devp, "testing append to file %d", un->un_fileno);	un->un_laststate = un->un_state;	un->un_state = ST_STATE_APPEND_TESTING;	un->un_test_append = 0;	/*	 * first, map in the buffer, because we're doing a double write --	 * first into the kernel, then onto the tape.	 */	bp_mapin(bp);	/*	 * get a copy of the data....	 */	un->un_tmpbuf = (caddr_t) kmem_alloc((unsigned) bp->b_bcount);	bcopy(bp->b_un.b_addr, un->un_tmpbuf, (u_int) bp->b_bcount);	/*	 * attempt the write..	 */	if (stcmd(devp, SCMD_WRITE, (int) bp->b_bcount, SYNC_CMD) == 0) {success:		DPRINTF(devp, "append write succeeded");		bp->b_resid = un->un_sbufp->b_resid;		/*		 * Note: iodone will do a bp_mapout()		 */		iodone(bp);		un->un_laststate = un->un_state;		un->un_state = ST_STATE_OPEN;		(void) kmem_free (un->un_tmpbuf, (unsigned)bp->b_bcount);		un->un_tmpbuf = 0;		return;	}	/*	 * The append failed. Do a short read. If that fails,  we are at EOM	 * so we can retry the write command. If that succeeds, than we're	 * all screwed up (the controller reported a real error).	 *	 * XXX:	should the dummy read be > SECSIZE? should it be the device's	 * XXX:	block size?	 *	 */	status = un->un_status;	un->un_status = 0;	(void) stcmd(devp, SCMD_READ, SECSIZE, SYNC_CMD);	if (un->un_status == KEY_BLANK_CHECK) {		DPRINTF(devp, "append at EOM");		/*		 * Okay- the read failed. We should actually have confused		 * the controller enough to allow writing. In any case, the		 * i/o is on its own from here on out.		 */		un->un_laststate = un->un_state;		un->un_state = ST_STATE_OPEN;		bcopy(bp->b_un.b_addr, un->un_tmpbuf, (u_int) bp->b_bcount);		if (stcmd(devp, SCMD_WRITE, (int) bp->b_bcount, SYNC_CMD) == 0)			goto success;	}	DPRINTF(devp, "append write failed- not at EOM");	bp->b_resid = bp->b_bcount;	bp->b_flags |= B_ERROR;	bp->b_error = EIO;	/*	 * backspace one record to get back to where we were	 */	if (stcmd(devp, SCMD_SPACE, Blk(-1), SYNC_CMD))		un->un_fileno = -1;	un->un_err_resid = bp->b_resid;	un->un_status = status;	/*	 * Note: iodone will do a bp_mapout()	 */	iodone(bp);	un->un_laststate = un->un_state;	un->un_state = ST_STATE_OPEN_PENDING_IO;	(void) kmem_free (un->un_tmpbuf, (unsigned)bp->b_bcount);	un->un_tmpbuf = 0;}/* * Special command handler *//* * common stcmd code. The fourth parameter states * whether the caller wishes to await the results */static intstcmd(devp, com, count, wait)register struct scsi_device *devp;int com, count, wait;{	struct scsi_tape *un = UPTR;	register struct buf *bp;	register s, error;#ifdef  ST_DEBUG	if (st_debug & ST_DEBUG_CMDS)		st_debug_cmds(devp, com, count, wait);#endif	bp = un->un_sbufp;	s = splr(stpri);	while (bp->b_flags & B_BUSY) {		bp->b_flags |= B_WANTED;		if (un->un_state == ST_STATE_OPENING) {			if (sleep((caddr_t) bp, (PZERO+1)|PCATCH)) {				bp->b_flags &= ~B_WANTED;				(void) splx(s);				return (EINTR);			}		} else {			(void) sleep((caddr_t) bp, PRIBIO);		}	}	if (!wait)		bp->b_flags = B_BUSY|B_ASYNC;	else		bp->b_flags = B_BUSY;	(void) splx(s);	if (com == SCMD_READ || com == SCMD_WRITE) {		bp->b_un.b_addr = un->un_tmpbuf;		if (com == SCMD_READ)			bp->b_flags |= B_READ;	}	bp->b_error = 0;	bp->b_dev = un->un_dev;	bp->b_bcount = count;	bp->b_resid = 0;	bp->b_forw = (struct buf *) com;	make_st_cmd(devp, bp, SLEEP_FUNC);	ststrategy(bp);	if (!wait) {		return (0);	}	s = splr(stpri);	while ((bp->b_flags & B_DONE) == 0) {		if (un->un_state == ST_STATE_OPENING) {			if (sleep((caddr_t) un, (PZERO+1)|PCATCH)) {				if (bp->b_flags & B_DONE)					break;				bp->b_flags |= B_ASYNC;				(void) splx(s);				return (EINTR);			}		} else			(void) sleep((caddr_t) un, PRIBIO);	}	error = geterror(bp);	scsi_resfree(BP_PKT(bp));	(void) splx(s);	if (com == SCMD_READ || com == SCMD_WRITE) {		bp->b_un.b_addr = (caddr_t) 0;	}	bp->b_flags &= ~B_BUSY;	if (bp->b_flags & B_WANTED) {		wakeup((caddr_t) bp);	}	return (error);}/* * We assume someone else has set the density code */static intst_modeselect(devp)struct scsi_device *devp;{	register struct scsi_tape *un = UPTR;	un->un_mspl->reserved1 = un->un_mspl->reserved2 = 0;	un->un_mspl->wp = 0;	if (un->un_dp->options & ST_NOBUF)		un->un_mspl->bufm = 0;	else		un->un_mspl->bufm = 1;	un->un_mspl->bd_len = 8;	un->un_mspl->high_nb = un->un_mspl->mid_nb = un->un_mspl->low_nb = 0;	if ((un->un_dp->options & ST_VARIABLE) == 0) {		un->un_mspl->high_bl = 0;		un->un_mspl->mid_bl = (un->un_dp->bsize>>8) & 0xff;		un->un_mspl->low_bl = (un->un_dp->bsize) & 0xff;	} else {		un->un_mspl->high_bl = un->un_mspl->mid_bl =			un->un_mspl->low_bl = 0;	}	if (stcmd(devp, SCMD_MODE_SELECT, MSIZE, SYNC_CMD) ||			stcmd(devp, SCMD_MODE_SENSE, MSIZE, SYNC_CMD)) {		if (un->un_state >= ST_STATE_OPEN) {			stprintf(devp, "unable to set tape mode");			un->un_fileno = -1;			return (ENXIO);		}		return (-1);	}	return (0);}static voidstinit(un)struct scsi_tape *un;{	un->un_blkno = 0;	un->un_fileno = 0;	un->un_lastop = ST_OP_NIL;	un->un_eof = ST_NO_EOF;	if (st_error_level != STERR_ALL) {		if (DEBUGGING)			st_error_level = STERR_ALL;		else			st_error_level = STERR_RETRYABLE;	}}static voidmake_st_cmd(devp, bp, func)register struct scsi_device *devp;register struct buf *bp;int (*func)();{	register struct scsi_pkt *pkt;	register struct scsi_tape *un = UPTR;	register count, com, flags, tval = st_io_time;	char fixbit = (un->un_dp->options & ST_VARIABLE) ? 0: 1;	flags = (scsi_options & SCSI_OPTIONS_DR) ? 0: FLAG_NODISCON;	if (un->un_dp->options & ST_NOPARITY)		flags |= FLAG_NOPARITY;	/*	 * fixbit is for setting the Fixed Mode and Suppress Incorrect	 * Length Indicator bits on read/write commands, for setting	 * the Long bit on erase commands, and for setting the Code	 * Field bits on space commands.	 *//* * XXX why do we set lastop here? */	if (bp != un->un_sbufp) {		/* regular raw I/O */		pkt = scsi_resalloc(ROUTE, C

⌨️ 快捷键说明

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