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

📄 ct.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)ct.c	8.2 (Berkeley) 1/12/94 */#include "ct.h"#if NCT > 0/* * CS80 cartridge tape driver (9144, 88140, 9145) * * Reminder: *	C_CC bit (character count option) when used in the CS/80 command *	'set options' will cause the tape not to stream. * * TODO: *	make filesystem compatible *	make block mode work according to mtio(4) spec. (if possible) *	merge with cs80 disk driver *	finish support of 9145 */#include <sys/param.h>#include <sys/buf.h>#include <sys/ioctl.h>#include <sys/mtio.h>#include <sys/tprintf.h>#include <sys/proc.h>#include <hp/dev/device.h>#include <hp300/dev/ctreg.h>/* number of eof marks to remember */#define EOFS	128int	ctinit(), ctstart(), ctgo(), ctintr();struct	driver ctdriver = {	ctinit, "ct", ctstart, ctgo, ctintr,};struct	ct_softc {	struct	hp_device *sc_hd;	struct	ct_iocmd sc_ioc;	struct	ct_rscmd sc_rsc;	struct	ct_stat sc_stat;	struct	ct_ssmcmd sc_ssmc;	struct	ct_srcmd sc_src;	struct	ct_soptcmd sc_soptc;	struct	ct_ulcmd sc_ul;	struct	ct_wfmcmd sc_wfm;	struct	ct_clearcmd sc_clear;	struct	buf *sc_bp;	int	sc_blkno;	int	sc_cmd;	int	sc_resid;	char	*sc_addr;	int	sc_flags;	short	sc_type;	short	sc_punit;	tpr_t	sc_tpr;	struct	devqueue sc_dq;	int	sc_eofp;	int	sc_eofs[EOFS];} ct_softc[NCT];/* flags */#define	CTF_OPEN	0x01#define	CTF_ALIVE	0x02#define	CTF_WRT		0x04#define	CTF_CMD		0x08#define	CTF_IO		0x10#define	CTF_BEOF	0x20#define	CTF_AEOF	0x40#define	CTF_EOT		0x80#define	CTF_STATWAIT	0x100#define CTF_CANSTREAM	0x200#define	CTF_WRTTN	0x400struct	ctinfo {	short	hwid;	short	punit;	char	*desc;} ctinfo[] = {	CT7946ID,	1,	"7946A",	CT7912PID,	1,	"7912P",	CT7914PID,	1,	"7914P",	CT9144ID,	0,	"9144",	CT9145ID,	0,	"9145",};int	nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);struct	buf cttab[NCT];struct	buf ctbuf[NCT];#define	CT_NOREW	4#define	CT_STREAM	8#define	UNIT(x)		(minor(x) & 3)#define	ctpunit(x)	((x) & 7)#ifdef DEBUGint ctdebug = 0;#define CDB_FILES	0x01#define CT_BSF		0x02#endifctinit(hd)	register struct hp_device *hd;{	register struct ct_softc *sc = &ct_softc[hd->hp_unit];	register struct buf *bp;	for (bp = cttab; bp < &cttab[NCT]; bp++)		bp->b_actb = &bp->b_actf;	sc->sc_hd = hd;	sc->sc_punit = ctpunit(hd->hp_flags);	if (ctident(sc, hd) < 0)		return(0);	ctreset(sc, hd);	sc->sc_dq.dq_ctlr = hd->hp_ctlr;	sc->sc_dq.dq_unit = hd->hp_unit;	sc->sc_dq.dq_slave = hd->hp_slave;	sc->sc_dq.dq_driver = &ctdriver;	sc->sc_flags |= CTF_ALIVE;	return(1);}ctident(sc, hd)	register struct ct_softc *sc;	register struct hp_device *hd;{	struct ct_describe desc;	u_char stat, cmd[3];	char name[7];	int id, i;	/*	 * Read device id and verify that:	 * 1. It is a CS80 device	 * 2. It is one of our recognized tape devices	 * 3. It has the proper physical unit number	 */	id = hpibid(hd->hp_ctlr, hd->hp_slave);	if ((id & 0x200) == 0)		return(-1);	for (i = 0; i < nctinfo; i++)		if (id == ctinfo[i].hwid)			break;	if (i == nctinfo || sc->sc_punit != ctinfo[i].punit)		return(-1);	id = i;	/*	 * Collect device description.	 * Right now we only need this to differentiate 7945 from 7946.	 * Note that we always issue the describe command to unit 0.	 */	cmd[0] = C_SUNIT(0);	cmd[1] = C_SVOL(0);	cmd[2] = C_DESC;	hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, cmd, sizeof(cmd));	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_EXEC, &desc, 37);	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));	bzero(name, sizeof(name));	if (!stat) {		register int n = desc.d_name;		for (i = 5; i >= 0; i--) {			name[i] = (n & 0xf) + '0';			n >>= 4;		}	}	switch (ctinfo[id].hwid) {	case CT7946ID:		if (bcmp(name, "079450", 6) == 0)			return(-1);		/* not really a 7946 */		/* fall into... */	case CT9144ID:	case CT9145ID:		sc->sc_type = CT9144;		sc->sc_flags |= CTF_CANSTREAM;		break;	case CT7912PID:	case CT7914PID:		sc->sc_type = CT88140;		break;	}	printf("ct%d: %s %stape\n", hd->hp_unit, ctinfo[id].desc,	       (sc->sc_flags & CTF_CANSTREAM) ? "streaming " : " ");	return(id);}ctreset(sc, hd)	register struct ct_softc *sc;	register struct hp_device *hd;{	u_char stat;	sc->sc_clear.unit = C_SUNIT(sc->sc_punit);	sc->sc_clear.cmd = C_CLEAR;	hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &sc->sc_clear,		sizeof(sc->sc_clear));	hpibswait(hd->hp_ctlr, hd->hp_slave);	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));	sc->sc_src.unit = C_SUNIT(CTCTLR);	sc->sc_src.nop = C_NOP;	sc->sc_src.cmd = C_SREL;	sc->sc_src.param = C_REL;	hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_src,		sizeof(sc->sc_src));	hpibswait(hd->hp_ctlr, hd->hp_slave);	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));	sc->sc_ssmc.unit = C_SUNIT(sc->sc_punit);	sc->sc_ssmc.cmd = C_SSM;	sc->sc_ssmc.refm = REF_MASK;	sc->sc_ssmc.fefm = FEF_MASK;	sc->sc_ssmc.aefm = AEF_MASK;	sc->sc_ssmc.iefm = IEF_MASK;	hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_ssmc,		sizeof(sc->sc_ssmc));	hpibswait(hd->hp_ctlr, hd->hp_slave);	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));	sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);	sc->sc_soptc.nop = C_NOP;	sc->sc_soptc.cmd = C_SOPT;	sc->sc_soptc.opt = C_SPAR;	hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_soptc,		sizeof(sc->sc_soptc));	hpibswait(hd->hp_ctlr, hd->hp_slave);	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));}/*ARGSUSED*/ctopen(dev, flag, type, p)	dev_t dev;	int flag, type;	struct proc *p;{	register struct ct_softc *sc = &ct_softc[UNIT(dev)];	u_char stat;	int cc;	if (UNIT(dev) >= NCT || (sc->sc_flags & CTF_ALIVE) == 0)		return(ENXIO);	if (sc->sc_flags & CTF_OPEN)		return(EBUSY);	sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);	sc->sc_soptc.nop = C_NOP;	sc->sc_soptc.cmd = C_SOPT;	if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM))		sc->sc_soptc.opt = C_SPAR | C_IMRPT;	else		sc->sc_soptc.opt = C_SPAR;	/* 	 * Check the return of hpibsend() and hpibswait().	 * Drive could be loading/unloading a tape. If not checked,	 * driver hangs. 	 */	cc = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,	              C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc));	if (cc != sizeof(sc->sc_soptc))		return(EBUSY);	hpibswait(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave);	cc = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, 	              &stat, sizeof(stat));	if (cc != sizeof(stat))		return(EBUSY);	sc->sc_tpr = tprintf_open(p);	sc->sc_flags |= CTF_OPEN;	return(0);}/*ARGSUSED*/ctclose(dev, flag)	dev_t dev;	int flag;{	register struct ct_softc *sc = &ct_softc[UNIT(dev)];	if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) &&	    (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */		ctcommand(dev, MTWEOF, 2);		ctcommand(dev, MTBSR, 1);		if (sc->sc_eofp == EOFS - 1)			sc->sc_eofs[EOFS - 1]--;		else			sc->sc_eofp--;#ifdef DEBUG		if(ctdebug & CT_BSF)			printf("ct%d: ctclose backup eofs prt %d blk %d\n",			       UNIT(dev), sc->sc_eofp, sc->sc_eofs[sc->sc_eofp]);#endif	}	if ((minor(dev) & CT_NOREW) == 0)		ctcommand(dev, MTREW, 1);	sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN);	tprintf_close(sc->sc_tpr);#ifdef DEBUG	if (ctdebug & CDB_FILES)		printf("ctclose: flags %x\n", sc->sc_flags);#endif	return(0);	/* XXX */}ctcommand(dev, cmd, cnt)	dev_t dev;	int cmd;	register int cnt;{	register struct ct_softc *sc = &ct_softc[UNIT(dev)];	register struct buf *bp = &ctbuf[UNIT(dev)];	register struct buf *nbp = 0;	if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) {		cnt = sc->sc_eofs[EOFS - 1] - cnt;		ctcommand(dev, MTREW, 1);		ctcommand(dev, MTFSF, cnt);		cnt = 2;		cmd = MTBSR;	}	if (cmd == MTBSF && sc->sc_eofp - cnt < 0) {		cnt = 1;		cmd = MTREW;	}	sc->sc_flags |= CTF_CMD;	sc->sc_bp = bp;	sc->sc_cmd = cmd;	bp->b_dev = dev;	if (cmd == MTFSF) {		nbp = (struct buf *)geteblk(MAXBSIZE);		bp->b_un.b_addr = nbp->b_un.b_addr;		bp->b_bcount = MAXBSIZE;	}again:	bp->b_flags = B_BUSY;	if (cmd == MTBSF) {		sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];		sc->sc_eofp--;#ifdef DEBUG		if (ctdebug & CT_BSF)			printf("ct%d: backup eof pos %d blk %d\n",			       UNIT(dev), sc->sc_eofp, 			       sc->sc_eofs[sc->sc_eofp]);#endif	}	ctstrategy(bp);	iowait(bp);	if (--cnt > 0)		goto again;	bp->b_flags = 0;	sc->sc_flags &= ~CTF_CMD;	if (nbp)		brelse(nbp);}ctstrategy(bp)	register struct buf *bp;{	register struct buf *dp;	register int s, unit;	unit = UNIT(bp->b_dev);	dp = &cttab[unit];	bp->b_actf = NULL;	s = splbio();	bp->b_actb = dp->b_actb;	*dp->b_actb = bp;	dp->b_actb = &bp->b_actf;	if (dp->b_active == 0) {		dp->b_active = 1;		ctustart(unit);	}	splx(s);}ctustart(unit)	register int unit;{	register struct ct_softc *sc = &ct_softc[unit];	register struct buf *bp;	bp = cttab[unit].b_actf;	sc->sc_addr = bp->b_un.b_addr;	sc->sc_resid = bp->b_bcount;	if (hpibreq(&sc->sc_dq))		ctstart(unit);}ctstart(unit)	register int unit;{	register struct ct_softc *sc = &ct_softc[unit];	register struct buf *bp, *dp;	register int i;	bp = cttab[unit].b_actf;again:	if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {		switch(sc->sc_cmd) {		case MTFSF:			bp->b_flags |= B_READ;			goto mustio;

⌨️ 快捷键说明

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