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

📄 ut.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic char *sccsid = "@(#)ut.c	4.1      ULTRIX  7/2/90";#endif	lint/************************************************************************ *									* *			Copyright (c) 1984, 1986, 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.	* *									* ************************************************************************//* * ut.c    6.1	   07/29/83 * * Modification history * * TU45 tape driver * System Industries Model 9700 Tape Drive, * emulates a TU45 on the UNIBUS. * *  9-Feb-86 - ricky palmer * *	Derived from 4.2BSD labeled: ut.c	6.1	83/07/29. *	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 * * 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. * * 14-Aug-87 - rjl * *	Fixed two mprintf's that had a extra argument which caused *	the system to panic when a tape error was encountered. * * 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. */#include "tj.h"#if NUT > 0 || defined(BINARY)#include "../data/ut_data.c"u_short utstd[] = { UTSTD, 0 };int utprobe(), utslave(), utattach(), utdgo(), utintr(), uttimer();struct uba_driver utdriver = { utprobe, utslave, utattach, utdgo,			       utstd, "tj", tjdinfo, "ut",			       utminfo, 0 };utprobe(reg)	caddr_t reg;{#ifdef lint	utintr(0);#endif	/*	 * The SI documentation says you must set the RDY bit	 * (even though it's read-only) to force an interrupt.	 */	((struct utdevice *) reg)->utcs1 = UT_IE|UT_NOP|UT_RDY;	DELAY(10000);	return (sizeof (struct utdevice));}utslave(ui, reg)	struct uba_device *ui;	caddr_t reg;{	/*	 * A real TU45 would support the slave present bit	 * int the drive type register, but this thing doesn't,	 * so there's no way to determine if a slave is present or not.	 */	 return(1);}utattach(ui)	struct uba_device *ui;{	register struct tj_softc *sc = &tj_softc[ui->ui_unit];	tjtout[ui->ui_unit] = ui->ui_mi->um_ctlr;	bcopy(DEV_UNKNOWN,sc->sc_device,strlen(DEV_UNKNOWN));}/* * Open the device with exclusive access. */utopen(dev, flag)	register dev_t dev;	register int flag;{	register struct uba_device *ui;	register struct tj_softc *sc;	register struct utdevice *utaddr;	register int sel = SEL(dev);	int unit = UNIT(dev);	int s;	if (unit >= nNTJ || (sc = &tj_softc[unit])->sc_openf ||	    (ui  = tjdinfo[unit]) == 0 || ui->ui_alive == 0) {		return (ENXIO);	}	utaddr	= (struct utdevice *)ui->ui_addr;	if ((utaddr->utds & UTDS_EOT) && (dis_eot_tj[unit] != DISEOT)) {		sc->sc_flags &= DEV_EOM;	} else {		sc->sc_flags = 0;	}	sc->sc_category_flags = 0;	sc->sc_dens = (((sel == MTHR) || (sel == MTHN)) ?			      UTTC_GCR : ((sel == MTMR) ||			      (sel == MTMN)) ? UTTC_PE : UTTC_NRZI) |			      UTTC_PDP11FMT | (ui->ui_slave&07);	if((sel == MTHR) || (sel == MTHN)) {		sc->sc_category_flags |= DEV_6250BPI;	}	if((sel == MTMR) || (sel == MTMN)) {		sc->sc_category_flags |= DEV_1600BPI;	}	if((sel == MTLR) || (sel == MTLN)) {		sc->sc_category_flags |= DEV_800BPI;	}get:	utcommand(dev, UT_SENSE, 1);	if (sc->sc_dsreg & UTDS_PIP) {		sleep((caddr_t) & lbolt, PZERO+1);		goto get;	}	if ((sc->sc_dsreg & UTDS_MOL) == 0) {		sc->sc_flags |= DEV_OFFLINE;		if(!(flag & FNDELAY)) {			DEV_UGH(sc->sc_device,unit,"offline");			return(EIO);		}	}	if ((flag & FWRITE) && (sc->sc_dsreg & UTDS_WRL)) {		sc->sc_flags |= DEV_WRTLCK;		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;	/*	 * For 6250 bpi take exclusive use of the UNIBUS.	 */	ui->ui_driver->ud_xclu = (sc->sc_dens & (UTTC_PE|UTTC_GCR))				  == UTTC_GCR;	s = spl6();	if (sc->sc_tact == 0) {		sc->sc_timo = INF;		sc->sc_tact = 1;		timeout(uttimer, (caddr_t)dev, 5*hz);	}	splx(s);	return (0);}utclose(dev, flag)	register dev_t dev;	register int flag;{	register struct tj_softc *sc = &tj_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)) {		utcommand(dev, UT_WEOF, 1);		sc->sc_flags &= ~DEV_EOM;		utcommand(dev, UT_WEOF, 1);		sc->sc_flags &= ~DEV_EOM;		utcommand(dev, UT_SREV, 1);		sc->sc_flags &= ~DEV_EOM;	}	if ((sel == MTLR) || (sel == MTMR) || (sel == MTHR)) {		utcommand(dev, UT_REW, 0);	}	sc->sc_openf = 0;	if ((sc->sc_dsreg & UTDS_EOT) && (dis_eot_tj[unit] != DISEOT)) {		sc->sc_flags |= DEV_EOM;	}}utcommand(dev, com, count)	register dev_t dev;	register int com;	register int count;{	register struct buf *bp = &cutbuf[UTUNIT(dev)];	register int s = spl5();	while (bp->b_flags&B_BUSY) {		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_command = com;	bp->b_repcnt = count;	bp->b_blkno = 0;	utstrategy(bp);	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. */utstrategy(bp)	register struct buf *bp;{	register struct uba_ctlr *um;	register struct tj_softc *sc = &tj_softc[UNIT(bp->b_dev)];	register struct buf *dp;	register int s;	register int unit = UNIT(bp->b_dev);	if ((sc->sc_flags & DEV_EOM) && !((sc->sc_flags & DEV_CSE) ||	    (dis_eot_tj[unit] & DISEOT))) {		bp->b_resid = bp->b_bcount;		bp->b_error = ENOSPC;		bp->b_flags |= B_ERROR;		iodone(bp);		return;	}	sc->sc_category_flags &= ~DEV_TPMARK;	/*	 * Put transfer at end of unit queue	 */	dp = &tjutab[unit];	bp->av_forw = NULL;	s = spl5();	if (dp->b_actf == NULL) {		dp->b_actf = bp;		/*		 * Transport not active, so...		 * put at end of controller queue		 */		dp->b_forw = NULL;		um = tjdinfo[unit]->ui_mi;		if (um->um_tab.b_actf == NULL)			um->um_tab.b_actf = dp;		else			um->um_tab.b_actl->b_forw = dp;		um->um_tab.b_actl = dp;	} else		dp->b_actl->av_forw = bp;	dp->b_actl = bp;	/*	 * If the controller is not busy, set it going.	 */	if (um->um_tab.b_state == 0)		utstart(um);	splx(s);}utstart(um)	register struct uba_ctlr *um;{	register struct utdevice *addr = (struct utdevice *)um->um_addr;	register struct buf *bp, *dp;	register struct tj_softc *sc;	register struct uba_device *ui;	int utunit, unit;	daddr_t blkno;loop:	/*	 * Scan controller queue looking for units with	 * transaction queues to dispatch	 */	if ((dp = um->um_tab.b_actf) == NULL)		return;	if ((bp = dp->b_actf) == NULL) {		um->um_tab.b_actf = dp->b_forw;		goto loop;	}	utunit = UTUNIT(bp->b_dev);	unit = UNIT(bp->b_dev);	ui = tjdinfo[unit];	sc = &tj_softc[unit];	/* note slave select, density, and format were merged on open */	addr->uttc = sc->sc_dens;	sc->sc_dsreg = addr->utds;	sc->sc_erreg = addr->uter;	sc->sc_resid = MASKREG(addr->utfc);	if ((sc->sc_flags & DEV_EOM) && !((sc->sc_flags & DEV_CSE) ||	    (dis_eot_tj[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) && 	    (bp->b_flags & B_READ)) {		bp->b_resid = 0;		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 utintr().	 */	sc->sc_flags &= ~DEV_WRITTEN;	if (sc->sc_openf < 0 || (addr->utds&UTDS_MOL) == 0) {		/*		 * 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 == &cutbuf[utunit]) {		/*		 * Execute a control operation with the specified		 * count.		 */		if (bp->b_command == UT_SENSE)			goto next;		/*		 * Set next state; handle timeouts		 */		if (bp->b_command == UT_REW) {			um->um_tab.b_state = SREW;			sc->sc_timo = 5*60;		} else {			um->um_tab.b_state = SCOM;			sc->sc_timo = imin(imax(10*(int)-					   bp->b_repcnt,60),5*60);		}		if (bp->b_command >= UT_SFORW &&		    bp->b_command <= UT_SREVF)			addr->utfc = -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 tape is correctly positioned, set up all the	 * registers but the csr, and give control over to the	 * UNIBUS adaptor routines, to wait for resources to	 * start I/O.	 */	if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) {		addr->utwc = -(((bp->b_bcount)+1)>>1);		addr->utfc = -bp->b_bcount;		if ((bp->b_flags&B_READ) == 0) {			/*			 * On write error retries erase the			 * inter-record gap before rewriting.			 */			if (um->um_tab.b_errcnt) {				if (um->um_tab.b_state != SERASED) {					um->um_tab.b_state = SERASE;					sc->sc_timo = 60;					addr->utcs1 = UT_ERASE|UT_IE|						      UT_GO;					return;				}			}			um->um_cmd = UT_WCOM;		} else			um->um_cmd = UT_RCOM;		sc->sc_timo = 60;		um->um_tab.b_state = SIO;		(void) ubago(ui);		return;	}	/*	 * Tape positioned incorrectly; seek forwards or	 * backwards to the correct spot.  This happens for	 * raw tapes only on error retries.	 */	um->um_tab.b_state = SSEEK;	if (blkno < bdbtofsb(bp->b_blkno)) {		addr->utfc = blkno - bdbtofsb(bp->b_blkno);		bp->b_command = UT_SFORW;	} else {		addr->utfc = bdbtofsb(bp->b_blkno) - blkno;		bp->b_command = UT_SREV;	}	sc->sc_timo = imin(imax(10 * -addr->utfc, 60), 5*60);dobpcmd:	/*	 * Perform the command setup in bp.	 */	addr->utcs1 = bp->b_command|UT_IE|UT_GO;	return;next:	/*	 * Advance to the next command in the slave queue,	 * posting notice and releasing resources as needed.	 */	if (um->um_ubinfo)		ubadone(um);	um->um_tab.b_errcnt = 0;	dp->b_actf = bp->av_forw;	iodone(bp);	goto loop;}/* * Start operation on controller -- * UNIBUS resources have been allocated. */utdgo(um)	register struct uba_ctlr *um;{	register struct utdevice *addr = (struct utdevice *)um->um_addr;	addr->utba = (u_short) um->um_ubinfo;	addr->utcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300)|UT_IE|UT_GO;}/* * UT interrupt handler */utintr(ut11)	int ut11;{	register struct buf *bp;	register struct uba_ctlr *um = utminfo[ut11];	register struct utdevice *addr;	register struct tj_softc *sc;	register int state;	register struct buf *dp;	int utunit, unit;	u_short cs2, cs1;	if ((dp = um->um_tab.b_actf) == NULL)		return;

⌨️ 快捷键说明

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