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

📄 mt.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic char *sccsid = "@(#)mt.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.	* *									* ************************************************************************//* * mt.c    6.1	   07/29/83 * * Modification history * * TM78/TU78 tape driver * * V1.0 - tresvik * *	Derived from 4.2BSD labeled: mt.c	6.1	83/07/29. *	Changed error message format. * *  5-Oct-84 - tresvik * *	Keep the tape from running off the end of the tape.  This fix *	will at least return an error it the utility cares to look at *	it.  `cat', for example ignores errors on output and the tape *	will still go off the end. * *  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 * * 19-Mar-86 - ricky palmer * *	Added new DEVIOCGET ioctl request code along with *	soft and hard error counters. V2.0 * * 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 i/o requests. * * 04-Dec-86 - pmk * *	Changed mprintf's to log just one entry. * * 08-Jan-87 - lp * *	Change MTSENSE in open to happen before looking at any status. * * 29-Jan-87 - lp * *	changed order of MTSENSE in open to guarantee correct state. * * 11-Feb-87 - robin * *	changed the slave routine to fail only if the drive is not there and *	to report unexpected interupts to the console and error log. * * 02-Mar-87 - pmk * *	Changed slave routine: return if sn > 4 (max # of slaves), *	check slave attn. addr. for correct unit & do MTID_CLR on *	controller errors. * * 09-May-87 - Ricky Palmer (rsp) * *	Added new code to correctly handle EOT in all cases, hard errors, *	and dual ported subsystems. * * 08-Jul-87 - rsp * *	Fixed sporadic problem with file skip/read combo causing EIO error. *	Also, added new code based on 4.3BSD driver to correctly handle *	MT_UNREAD and MT_RDOPP interrupts (also involved minor change to *	MT_DONE data interrupt code). * * 07-Dec-87 - rsp * *	Fixed minor bug that showed up infrequently on semi-faulty *	formatter hardware involving a reset off a formatter that *	momentarily drops offline. Change is in mtndtint. * * 14-Feb-1989 - Tim Burke * *	Changed calls to DELAY(x) where the value of x is less than 10000 to *	be 100,000.  This is necessary because the granularity of the clock *	is 10000 as the smallest value (10 miliseconds). * * 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 "mu.h"#if NMT > 0 || defined(BINARY)#include "../data/mt_data.c"short	mttypes[] = { MBDT_TU78, 0 };int	mtattach(),mtslave(),mtustart(),mtstart(),mtndtint(),mtdtint();struct	mba_driver mtdriver = { mtattach, mtslave, mtustart, mtstart,				mtdtint, mtndtint, mttypes, "mt",				"mu", mtinfo };mtattach(mi)	register struct mba_device *mi;{}mtslave(mi, ms, sn)	register struct mba_device *mi;	register struct mba_slave *ms;	register int sn;{	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;	register struct mu_softc *sc = &mu_softc[ms->ms_unit];	register int s = spl7();	int ner, ds;	int rtn = 0;	if (sn < 4) {	    mtaddr->mtid = MTID_CLR;	    DELAY(100000);	    while ((mtaddr->mtid & MTID_RDY) == 0)		    ;	    mtaddr->mtas = -1;	    mtaddr->mtncs[sn] = MT_SENSE|MT_GO;	    DELAY(100000);	    while (mtaddr->mtas == 0)		    ;	    ner = mtaddr->mtner;	    ds = mtaddr->mtds;	    if (((ner >> 8) & 0x3) == sn) {		if (ds & MTDS_PRES) {		    sc->sc_mi = mi;		    sc->sc_slave = sn;		    mutomt[ms->ms_unit] = mi->mi_unit;		    rtn = 1;		    sc->sc_softcnt = 0;		    sc->sc_hardcnt = 0;		    switch(*(mi->mi_driver->md_type + mi->mi_type)) {		    case MBDT_TU78:			bcopy(DEV_TU78,sc->sc_device, strlen(DEV_TU78));			break;		    default:			bcopy(DEV_UNKNOWN,sc->sc_device, strlen(DEV_UNKNOWN));			break;		    }		}	    }	    switch (ner & MTER_INTCODE) {	    case MTER_DONE:		break;	    case MTER_TMFLTB:	    case MTER_MBFLT:	    case MTER_NOTAVL:		if (!(ds & MTDS_ONL)) {		    mtaddr->mtid = MTID_CLR;		    DELAY(100000);		    while ((mtaddr->mtid & MTID_RDY) == 0)			    ;		}		if(ner & MTER_NOTAVL || ner & MTER_ONLINE)		    break;	    default:		printf("mu%d: Unexpected Interupt 0%o Failure Code 0%o ds 0%o\n",			((ner >> 8) & 0x3), (ner & MTER_INTCODE),			((ner >> 10) & 0x3f), ds & 0xffff);		break;	    }	    mtaddr->mtas = mtaddr->mtas;	    DELAY(100000);	}	splx(s);	return (rtn);}mtopen(dev, flag)	register dev_t dev;	register int flag;{	register struct mba_device *mi;	register struct mu_softc *sc;	register int unit = UNIT(dev);	register int sel = SEL(dev);	if (unit >= nNMU || (sc = &mu_softc[unit])->sc_openf ||	    (mi = mtinfo[MTUNIT(dev)]) == 0 || mi->mi_alive == 0 ||	    sc->sc_mi == 0 ) {		return (ENXIO);	}	sc->sc_dens =	    ((sel == MTHR) || (sel == MTHN)) ? MT_GCR : 0;	sc->sc_flags = 0;	mtcommand(dev, MT_SENSE, 1);	if((sc->sc_dsreg & MTDS_AVAIL) == 0) {		return(ENXIO);	}	if ((sc->sc_dsreg & MTDS_EOT) &&	    (dis_eot_mu[unit] != DISEOT)) {		sc->sc_flags = DEV_EOM;	} else {		sc->sc_flags = 0;	}	sc->sc_category_flags = 0;	if((sel == MTHR) || (sel == MTHN)) {		sc->sc_category_flags |= DEV_6250BPI;	} else {		sc->sc_category_flags |= DEV_1600BPI;	}	if (!(sc->sc_dsreg & MTDS_ONL)) {		sc->sc_flags |= DEV_OFFLINE;		if(!(flag & FNDELAY)) {			DEV_UGH(sc->sc_device,unit,"offline");			return(EIO);		}	}	if (sc->sc_dsreg & MTDS_FPT) {		sc->sc_flags |= DEV_WRTLCK;	}	if ((flag & FWRITE) && (sc->sc_dsreg & MTDS_FPT)) {		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;	sc->sc_firsttime = 1;	sc->sc_changedstate = 0;	sc->sc_savestate = sc->sc_dsreg;	return (0);}mtclose(dev, flag)	register dev_t dev;	register int flag;{	register struct mu_softc *sc = &mu_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))) {		mtcommand(dev, MT_CLS|sc->sc_dens, 1);		sc->sc_flags &= ~DEV_EOM;	}	if ((sel == MTLR) || (sel == MTHR)) {		mtcommand(dev, MT_REW, 0);	}	sc->sc_openf = 0;	if ((sc->sc_dsreg & MTDS_EOT) && (dis_eot_mu[unit] != DISEOT)){		sc->sc_flags |= DEV_EOM;	}}mtcommand(dev, com, count)	register dev_t dev;	register int com;	register int count;{	register struct buf *bp = &cmtbuf[MTUNIT(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;	mtstrategy(bp);	if (count == 0)		return;	iowait(bp);	if (bp->b_flags&B_WANTED)		wakeup((caddr_t)bp);	bp->b_flags &= B_ERROR;}mtstrategy(bp)	register struct buf *bp;{	register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;	register struct mu_softc *sc = &mu_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_mu[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;	}	bp->av_forw = NULL;	dp = &mi->mi_tab;	s = spl5();	if (dp->b_actf == NULL)		dp->b_actf = bp;	else		dp->b_actl->av_forw = bp;	dp->b_actl = bp;	if (dp->b_active == 0)		mbustart(mi);	splx(s);}mtustart(mi)	register struct mba_device *mi;{	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;	register struct buf *bp = mi->mi_tab.b_actf;	register struct mu_softc *sc = &mu_softc[UNIT(bp->b_dev)];	register int mtunit = MTUNIT(bp->b_dev);	register daddr_t blkno;	int unit = UNIT(bp->b_dev);	if ((sc->sc_flags & DEV_EOM) && !((sc->sc_flags & DEV_CSE) ||	    (dis_eot_mu[unit] & DISEOT))) {		bp->b_resid = bp->b_bcount;		bp->b_error = ENOSPC;		bp->b_flags |= B_ERROR;		return (MBU_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;		return (MBU_NEXT);	}	sc->sc_flags &= ~DEV_WRITTEN;	if (sc->sc_openf < 0) {		bp->b_flags |= B_ERROR;		return (MBU_NEXT);	}	if (bp != &cmtbuf[mtunit]) {		if (sc->sc_blkno != bdbtofsb(bp->b_blkno) &&			!mi->mi_tab.b_errcnt)			sc->sc_blkno = bdbtofsb(bp->b_blkno);	sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1;	} else {		mtaddr->mtncs[unit] =			(bp->b_repcnt<<8)|bp->b_command|MT_GO;		return (MBU_STARTED);	}	if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) {		if (mi->mi_tab.b_errcnt == 2) {			mtaddr->mtca = unit;		} else {			mtaddr->mtbc = bp->b_bcount;			mtaddr->mtca = (1<<2)|unit;		}		return (MBU_DODATA);	}	if (blkno < bdbtofsb(bp->b_blkno))		mtaddr->mtncs[unit] =		  (min((unsigned)(bdbtofsb(bp->b_blkno) - blkno),		   0377) << 8) | MT_SFORW|MT_GO;	else		mtaddr->mtncs[unit] =		  (min((unsigned)(blkno - bdbtofsb(bp->b_blkno)),		   0377) << 8) | MT_SREV|MT_GO;	return (MBU_STARTED);}mtstart(mi)	register struct mba_device *mi;{	register struct buf *bp = mi->mi_tab.b_actf;	register struct mu_softc *sc = &mu_softc[UNIT(bp->b_dev)];	if (bp->b_flags & B_READ)		if (mi->mi_tab.b_errcnt == 2) {			return(MT_READREV|MT_GO);		} else {			if(sc->sc_firsttime || sc->sc_changedstate) {				sc->sc_changedstate = 0;				sc->sc_firsttime = 0;				sc->sc_savestate = sc->sc_dsreg;				return(MT_READ|MT_SENSE|MT_GO);			} else				return(MT_READ|MT_GO);		}	else		return(MT_WRITE|sc->sc_dens|MT_GO);}mtdtint(mi, mbsr)	register struct mba_device *mi;	int mbsr;{	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;	register struct buf *bp = mi->mi_tab.b_actf;	register struct mu_softc *sc = &mu_softc[UNIT(bp->b_dev)];	register int mtunit = MTUNIT(bp->b_dev);	register int unit = UNIT(bp->b_dev);	sc->sc_erreg = mtaddr->mter;	if((bp->b_flags & B_READ) == 0)		sc->sc_flags |= DEV_WRITTEN;	switch (sc->sc_erreg & MTER_INTCODE) {	case MTER_DONE:	case MTER_LONGREC:		sc->sc_flags |= DEV_DONE;		if (mi->mi_tab.b_errcnt != 2)			sc->sc_blkno++;		if (mi->mi_tab.b_errcnt == 2) {			bp->b_bcount = bp->b_resid;			bp->b_resid -= MASKREG(mtaddr->mtbc);			if ((bp->b_resid > 0) && (bp == &cmtbuf[mtunit]))				bp->b_flags |= B_ERROR;		} else {

⌨️ 快捷键说明

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