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

📄 ts.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic char *sccsid = "@(#)ts.c	4.1      (ULTRIX)        7/2/90";#endif	lint/************************************************************************ *									* *			Copyright (c) 1984, 1986, 1987, 1989 by		* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any	other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived	from  software	received  from	the	* *   University    of	California,   Berkeley,   and	from   Bell	* *   Laboratories.  Use, duplication, or disclosure is	subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or	reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * ts.c    6.1	   07/29/83 * * Modification history * * TS11/TSU05/TSV05/TU80 tape driver * * 22-Jan-85 - Larry Cohen * *	Derived from 4.2BSD labeled: ts.c	6.1	83/07/29. *	Make probe routine interrupt device instead of hard wired *	interrupt vectors. LSC001: * *  6-Mar-85 - Larry Cohen * *	Make probe route interrupt correctly. LSC002: * * 13-Mar-85 - jaw * *	Add support for VAX8200. * * 19-Jun-85 - jaw * *	VAX8200 name change. * * 11-Jul-85 - jaw * *	Fix bua/bda map registers. * *  6-Aug-85 - ricky palmer * *	Added new ioctl functionality as well as new code to handle *	EOT correctly. Driver now supports new minor number convention *	to allow for more than 4 tape devices. V2.0 * *  8-Feb-86 - ricky palmer * *	Added streaming tape support for ts05/tsv05 subsystem. V2.0 * * 18-Mar-86 - jaw * *	br/cvec changed to NOT use registers. * * 19-Mar-86 - ricky palmer * *	Added new DEVIOCGET ioctl request code. V2.0 * * 13-Jun-86 - jaw * *	Fix to uba reset and drivers. * * 11-Jul-86 - ricky palmer * *	Added adpt and nexus fields to DEVIOCGET code. * * 26-Aug-86 - rsp (Ricky Palmer) * *	Cleaned up devioctl code to (1) zero out devget structure *	upon entry and (2) use strlen instead of fixed storage *	for bcopy's. * * 30-Oct-86 - lp * *	TPMARK & HARDERR now prevent further n-buffered requests. * * 04-Dec-86 - pmk * *	Changed mprintf to log just one entry. * * 08-Jul-87 - rsp * *	Corrected attach routine to correctly fill in TS05 device string. * * 05-MAY-89 - dallas *	Modified the ts_init and ts_probe routines to not set any of the *	bits in the extended characteristics data word for the wrt. char. *	command. The set of these bits are for diag's purposes only. To * 	bad the documentation leads you to believe that you should be *	mucking with the word. Setting of the bits in the word really *	confuses the controller. Also added global int ts_softerr and a *	mprintf - for field service and css purposes. With adb the setting *	of the int allows all soft errors to be reported to the errlog.  * * 05-Jun-89 - Tim Burke *    Added a new MTIOCTOP called MTFLUSH.  This is used on caching drives *    to force a flush of the controller's write back cache.  Since this *    is not a caching drive the MTFLUSH always returns ENXIO. * * 22-Jul-89 - kuo-hsiung hsieh *	Added codes for mipsfair (DS_5400). * * 05-DEC-89 - Bill Dallas *	In tswait changed the declaration of register int s to *	register volatile int s This change is for the mips compiler *	optimization of the assign out of the do while loop if *	not declared as volatile. */#include "ts.h"#if NTS > 0 || defined(BINARY)#include "../data/ts_data.c"extern int cpu;u_short tsstd[] = { TSSTD, 0 };int	tsprobe(), tsslave(), tsattach(), tsdgo(), tsintr();struct	uba_driver zsdriver = { tsprobe, tsslave, tsattach, tsdgo,				tsstd, "ts", tsdinfo, "zs",				tsminfo, 0 };int ts_softerr = 0;	/* declared for soft error reports..Field service		 	 * needs this.. Reasons for not streaming - dallas *//* * Determine if there is a controller for * a ts at address reg.  The goal is to make the * device interrupt. */tsprobe(reg, ctrl)	caddr_t reg;	int ctrl;{	int i, ubaddr, uba_cmdaddr;	struct ts_softc *sc;#ifdef lint	tsintr(0);#endif lint	((struct tsdevice *)reg)->tssr = 0;/* * LSC001: * LSC002: */	DELAY(5000000);	if ((((struct tsdevice *)reg)->tssr & TS_NBA) == 0)		return(0);	sc = &ts_softc[ctrl];	ctsbuf[ctrl].b_un.b_addr = (caddr_t)sc;	ctsbuf[ctrl].b_bcount = sizeof(*sc);	ubaddr = ubasetup(numuba, &ctsbuf[ctrl], 0);	i = ubaddr & 0777777;	sc->sc_ubaddr = (struct ts_softc *)i;	uba_cmdaddr = (int)&sc->sc_ubaddr->sc_cmd;	sc->sc_uba = (u_short)(uba_cmdaddr + ((uba_cmdaddr>>16)&3));	sc->sc_char.char_addr = (int)&sc->sc_ubaddr->sc_sts;	sc->sc_char.char_size = sizeof(struct ts_sts);	sc->sc_char.char_mode = TS_ESS;	/* dallas get rid of following line these bits are only for diags.	 * and seems to really confuse the drive/controller 	 * sc->sc_char.char_modext = TS_ENHSP|TS_ENBUF;*/		sc->sc_char.char_modext = 0; /* make sure 0 for tsv and tsu controllers,					for ts11 controllers it ignores them. */ 	sc->sc_cmd.c_cmd = TS_ACK | TS_IE | TS_SETCHR;	i = (int)&sc->sc_ubaddr->sc_char;	sc->sc_cmd.c_loba = i;	sc->sc_cmd.c_hiba = (i>>16)&3;	sc->sc_cmd.c_size = sizeof(struct ts_char);	((struct tsdevice *)reg)->tsdb = sc->sc_uba;	DELAY(5000000);	if (cvec && cvec == 0x200)  /* check for interrupt */		ubarelse(numuba, &ubaddr); /* release resources */	else		sc->sc_mapped++;	((struct tsdevice *)reg)->tssr = 0; /* reset device so					     * first open					     * does not hang					     */	DELAY(100000);	return (sizeof (struct tsdevice));}/* * TS11 only supports one drive per controller; * check for ui_slave == 0. */tsslave(ui, reg)	struct uba_device *ui;	caddr_t reg;{	if (ui->ui_slave)	/* non-zero slave not allowed */		return(0);	return (1);}/* * Record attachment of the unit to the controller. */tsattach(ui)	struct uba_device *ui;{	register struct ts_softc *sc = &ts_softc[ui->ui_unit];	sc->sc_softcnt = 0;	sc->sc_hardcnt = 0;	if(sc->sc_sts.s_xs2 & TS_TU80) {		bcopy(DEV_TU80,sc->sc_device,strlen(DEV_TU80));	} else {		if(ui->ui_hd->uba_type & (UBAUVI|UBAUVII)) {			bcopy(DEV_TS05,sc->sc_device,strlen(DEV_TS05));		} else {			bcopy(DEV_TS11,sc->sc_device,strlen(DEV_TS11));		}	}}/* * Open the device.  Tapes are unique open * devices, so we refuse if it is already open. * We also check that a tape is available, and * don't block waiting here; if you want to wait * for a tape you should timeout in user code. */tsopen(dev, flag)	register dev_t dev;	register int flag;{	register struct uba_device *ui;	register struct ts_softc *sc;	register int unit = UNIT(dev);	if (unit >= nNTS || (sc = &ts_softc[unit])->sc_openf ||	    (ui = tsdinfo[unit]) == 0 || ui->ui_alive == 0) {		return (ENXIO);	}	if ((sc->sc_sts.s_xs0 & TS_EOT) && (dis_eot_ts[unit] !=	    DISEOT)) {		sc->sc_flags &= DEV_EOM;	} else {		sc->sc_flags = 0;	}	sc->sc_category_flags = 0;	if (tsinit(unit))		return (ENXIO);	tscommand(dev, TS_SENSE, 1);	sc->sc_category_flags |= DEV_1600BPI;	if((strcmp(DEV_TS05,sc->sc_device)) == 0) {		DELAY(100000);		tscommand(dev, TS_SENSE, 1);	}	if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) {		sc->sc_flags |= DEV_OFFLINE;		if(!(flag & FNDELAY)) {			DEV_UGH(sc->sc_device,unit,"offline");			return(EIO);		}	}	if (sc->sc_sts.s_xs0 & TS_WLK) {		sc->sc_flags |= DEV_WRTLCK;	}	if ((flag & (FREAD|FWRITE)) == FWRITE &&	    (sc->sc_sts.s_xs0 & TS_WLK)) {		if(!(flag & FNDELAY)) {			DEV_UGH(sc->sc_device,unit,"write locked");			return(EIO);		}	}	sc->sc_openf = 1;	sc->sc_blkno = (daddr_t)0;	sc->sc_nxrec = INF;	return (0);}/* * Close tape device. * * If tape was open for writing or last operation was * a write, then write two EOF's and backspace over the last one. * Unless this is a non-rewinding special file, rewind the tape. * Make the tape available to others. */tsclose(dev, flag)	register dev_t dev;	register int flag;{	register struct ts_softc *sc = &ts_softc[UNIT(dev)];	register int unit = UNIT(dev);	register int sel = SEL(dev);	sc->sc_flags &= ~DEV_EOM;	if (flag == FWRITE || (flag&FWRITE) &&	    (sc->sc_flags & DEV_WRITTEN)) {		tscommand(dev, TS_WEOF, 1);		sc->sc_flags &= ~DEV_EOM;		tscommand(dev, TS_WEOF, 1);		sc->sc_flags &= ~DEV_EOM;		tscommand(dev, TS_SREV, 1);		sc->sc_flags &= ~DEV_EOM;	}	if (sel == MTHR)		/*		 * 0 count means don't hang waiting for rewind complete		 * rather ctsbuf stays busy until the operation		 * completes preventing further opens from completing		 * by preventing a TS_SENSE from completing.		 */		tscommand(dev, TS_REW, 0);	sc->sc_openf = 0;	if ((sc->sc_sts.s_xs0 & TS_EOT) && (dis_eot_ts[unit] !=	    DISEOT)) {		sc->sc_flags |= DEV_EOM;	}}/* * Initialize the TS11.  Set up bus mapping for command * packets and set device characteristics. */tsinit(unit)	register int unit;{	register struct ts_softc *sc = &ts_softc[unit];	register struct uba_ctlr *um = tsminfo[unit];	register struct tsdevice *addr = (struct tsdevice *)um->um_addr;	register int i;	/*	 * Map the command and message packets into bus	 * address space.  We do all the command and message	 * packets at once to minimize the amount of bus	 * mapping necessary.	 */	if (sc->sc_mapped == 0) {		ctsbuf[unit].b_un.b_addr = (caddr_t)sc;		ctsbuf[unit].b_bcount = sizeof(*sc);		i = ubasetup(um->um_ubanum, &ctsbuf[unit], 0);		i &= 0777777;		sc->sc_ubaddr = (struct ts_softc *)i;		sc->sc_mapped++;	}	/*	 * Now initialize the TS11 controller.	 * Set the characteristics.	 */	if (addr->tssr & (TS_NBA|TS_OFL)) {		addr->tssr = 0; 	/* subsystem initialize */		tswait(addr);		i = (int)&sc->sc_ubaddr->sc_cmd;  /* bus addr of cmd */		sc->sc_uba = (u_short)(i + ((i>>16)&3));		sc->sc_char.char_addr = (int)&sc->sc_ubaddr->sc_sts;		sc->sc_char.char_size = sizeof(struct ts_sts);		sc->sc_char.char_mode = TS_ESS;		/* get rid of this line, bits only for diags and really		 * confuses the tsv05		 * sc->sc_char.char_modext = TS_ENHSP|TS_ENBUF; */ 		sc->sc_char.char_modext = 0; /* for tsv and tsu controllers						ts11 controllers ignore them. */		sc->sc_cmd.c_cmd = TS_ACK | TS_SETCHR;		i = (int)&sc->sc_ubaddr->sc_char;		sc->sc_cmd.c_loba = i;		sc->sc_cmd.c_hiba = (i>>16)&3;		sc->sc_cmd.c_size = sizeof(struct ts_char);		addr->tsdb = sc->sc_uba;		tswait(addr);		if (addr->tssr & TS_NBA)			return(1);	}	return(0);}/* * Execute a command on the tape drive * a specified number of times. */tscommand(dev, com, count)	register dev_t dev;	register int com;	register int count;{	register struct buf *bp = &ctsbuf[UNIT(dev)];	register int s = splbio();	while (bp->b_flags & B_BUSY) {		/*		 * This special check is because B_BUSY never		 * gets cleared in the non-waiting rewind case.		 */		if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE))			break;		bp->b_flags |= B_WANTED;		sleep((caddr_t)bp, PRIBIO);	}	bp->b_flags = B_BUSY|B_READ;	splx(s);	bp->b_dev = dev;	bp->b_repcnt = count;	bp->b_command = com;	bp->b_blkno = 0;	tsstrategy(bp);	/*	 * In case of rewind from close, don't wait.	 * This is the only case where count can be 0.	 */	if (count == 0)		return;	iowait(bp);	if (bp->b_flags & B_WANTED)		wakeup((caddr_t)bp);	bp->b_flags &= B_ERROR;}/* * Queue a tape operation. */tsstrategy(bp)	register struct buf *bp;{	register struct uba_ctlr *um;	register struct ts_softc *sc = &ts_softc[UNIT(bp->b_dev)];	register struct buf *dp;	register int s;	int unit = UNIT(bp->b_dev);	if ((sc->sc_flags & DEV_EOM) && !((sc->sc_flags & DEV_CSE) ||	    (dis_eot_ts[unit] & DISEOT))) {		bp->b_resid = bp->b_bcount;		bp->b_error = ENOSPC;		bp->b_flags |= B_ERROR;		iodone(bp);		return;	}	if((bp->b_flags&B_READ) && (bp->b_flags&B_RAWASYNC) &&		((sc->sc_category_flags&DEV_TPMARK) || (sc->sc_flags&DEV_HARDERR))) {		bp->b_error = EIO;		bp->b_flags |= B_ERROR;		iodone(bp);		return;	}	/*	 * Put transfer at end of controller queue	 */	bp->av_forw = NULL;	um = tsdinfo[unit]->ui_mi;	s = splbio();	dp = &tsutab[unit];	if (dp->b_actf == NULL)		dp->b_actf = bp;	else		dp->b_actl->av_forw = bp;	dp->b_actl = bp;	um->um_tab.b_actf = um->um_tab.b_actl = dp;	/*	 * If the controller is not busy, get	 * it going.	 */	if (um->um_tab.b_active == 0)		tsstart(um);	splx(s);}/* * Start activity on a ts controller. */tsstart(um)	register struct uba_ctlr *um;{	register struct tsdevice *addr = (struct tsdevice *)um->um_addr;	register struct buf *bp;	register struct ts_softc *sc;	register struct ts_cmd *tc;	struct uba_device *ui;	int cmd, unit;	daddr_t blkno;loop:	/*	 * Start the controller if there is something for it to do.	 */	if ((bp = um->um_tab.b_actf->b_actf) == NULL)		return;	unit = UNIT(bp->b_dev);	ui = tsdinfo[unit];	sc = &ts_softc[unit];	tc = &sc->sc_cmd;	if ((sc->sc_flags & DEV_EOM) && !((sc->sc_flags & DEV_CSE) ||	    (dis_eot_ts[unit] & DISEOT))) {		bp->b_resid = bp->b_bcount;		bp->b_error = ENOSPC;		bp->b_flags |= B_ERROR;		goto next;	}	if (((sc->sc_category_flags&DEV_TPMARK) ||(sc->sc_flags&DEV_HARDERR)) &&	    (bp->b_flags & B_READ) && (bp->b_flags&B_RAWASYNC)) {		bp->b_error = EIO;		bp->b_flags |= B_ERROR;		goto next;	}	/*	 * Default is that last command was NOT a write command;	 * if we do a write command we will notice this in tsintr().	 */	sc->sc_flags &= ~DEV_WRITTEN;	if (sc->sc_openf < 0 || (addr->tssr & TS_OFL)) {		/*		 * Have had a hard error on a non-raw tape		 * or the tape unit is now unavailable		 * (e.g. taken off line).		 */		bp->b_flags |= B_ERROR;		goto next;	}	if (bp == &ctsbuf[unit]) {		/*		 * Execute control operation with the specified count.		 */		um->um_tab.b_active =		    bp->b_command == TS_REW ? SREW : SCOM;		tc->c_repcnt = bp->b_repcnt;		goto dobpcmd;	}	if (sc->sc_blkno != bdbtofsb(bp->b_blkno) &&	    !um->um_tab.b_errcnt)		sc->sc_blkno = bdbtofsb(bp->b_blkno);	sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1;	/*	 * If the data transfer command is in the correct place,	 * set up all the registers except the csr, and give	 * control over to the BUS adapter routines, to	 * wait for resources to start the i/o.	 */	if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) {		tc->c_size = bp->b_bcount;		if ((bp->b_flags&B_READ) == 0)			cmd = TS_WCOM;		else			cmd = TS_RCOM;		if (um->um_tab.b_errcnt) {			cmd |= TS_RETRY;			sc->sc_softcnt++;			sc->sc_flags |= DEV_RETRY;		}		um->um_tab.b_active = SIO;		tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd;		(void) ubago(ui);		return;	}

⌨️ 快捷键说明

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