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

📄 st.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1990 University of Utah. * Copyright (c) 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * 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. * * from: Utah $Hdr: st.c 1.11 92/01/21$ * *      @(#)st.c	8.3 (Berkeley) 1/12/94 *//* * SCSI CCS (Command Command Set) tape driver. * * Specific to Exabyte: * mt status: residual="Mbytes to LEOM" * minor bit 4 [b1bbbb] (aka /dev/rst16) selects short filemarks * minor bit 5 [1bbbbb] (aka /dev/rst32) selects fix block mode, 1k blocks. * * Archive drive: * can read both QIC-24 and QIC-II. But only writes * QIC-24. *  * Supports Archive Viper QIC-150 tape drive, but scsi.c reports selection * errors. * * Supports Archive Python DAT drive, but will sometimes hang machine. * * Supports HP 35450A DAT drive, but will sometimes hang machine. * Partitioning of tape not supported. * Vendor unique support has not been added. * * * Supports Archive VIPER (QIC-150). * Mostly Supports Archive PYTHON (DAT).  *     Hangs if write after spin down.  *     Need scsi.c that does connect/disconnect. *//* * support for the block device not implemented  */#include "st.h"#if NST > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/buf.h>#include <sys/file.h>#include <sys/proc.h>#include <sys/ioctl.h>#include <sys/tty.h>#include <sys/mtio.h>#include <sys/kernel.h>#include <sys/tprintf.h>#include <hp/dev/device.h>#include <hp300/dev/scsireg.h>#include <hp300/dev/stvar.h>extern int scsi_test_unit_rdy();extern int scsi_request_sense();extern int scsiustart();extern int scsigo();extern void scsifree();extern void scsireset();extern void scsi_delay();extern int scsi_tt_oddio();extern int scsi_immed_command();int	stinit(), ststart(), stgo(), stintr();struct	driver stdriver = {	stinit, "st", ststart, stgo, stintr,};struct	st_softc {	struct	hp_device *sc_hd;	struct	devqueue sc_dq;	long	sc_blkno;       /* (possible block device support?) */	long	sc_resid;	/* (possible block device support?) */	int	sc_flags;	int	sc_blklen;	/* 0 = variable len records */	int	sc_filepos;	/* file position on tape */	long	sc_numblks;	/* number of blocks on tape */	short	sc_type;	/* ansi scsi type */	short	sc_punit;	/* physical unit (scsi lun) */	short	sc_tapeid;	/* tape drive id */	char	sc_datalen[32];	/* additional data length on some commands */	short	sc_tticntdwn;	/* interrupts between TTi display updates */	tpr_t	sc_ctty;	struct	buf *sc_bp;	u_char	sc_cmd;} st_softc[NST];/* softc flags */#define STF_ALIVE	0x0001#define STF_OPEN	0x0002#define STF_WMODE	0x0004#define STF_WRTTN	0x0008#define STF_CMD		0x0010#define STF_LEOT	0x0020#define STF_MOVED	0x0040struct	st_mode st_mode[NST];/* * Maybe this should not be global, but gives chance to get * tape remaining, Rewrites/ECC, etc outside the driver  */static struct st_xsense {	struct	scsi_xsense sc_xsense;	/* data from sense */	struct	exb_xsense exb_xsense;	/* additional info from exabyte */} st_xsense[NST];static struct scsi_fmt_cdb stcmd[NST];static struct scsi_fmt_cdb st_read_cmd = { 6, CMD_READ };static struct scsi_fmt_cdb st_write_cmd = { 6, CMD_WRITE };struct buf sttab[NST];struct buf stbuf[NST];#define UNIT(x)		(minor(x) & 3)#define stpunit(x)	((x) & 7)#define STDEV_NOREWIND	0x04#define STDEV_HIDENSITY	0x08#define STDEV_EXSFMK	0x10#define STDEV_FIXEDBLK	0x20#ifdef DEBUGint st_debug = 0x0000;#define ST_OPEN		0x0001#define ST_GO		0x0002#define ST_FMKS		0x0004#define ST_OPENSTAT	0x0008#define ST_BRESID	0x0010#define ST_ODDIO	0x0020#endif/* * Patchable variable.  If an even length read is requested a dma transfer is * used.  Only after the read will we find out if the read had an odd number * of bytes.  The HP98658 hardware cannot do odd length transfers, the last * byte of the data will always be 0x00.  Normally, the driver will complain * about such transfers and return EIO.  However, if st_dmaoddretry is non- * zero, the driver will try and issue a BSR and then re-read the data using * 'programmed transfer mode'.  In most cases this works, however for unknown * reasons it will hang the machine in certain cases. * * Note: * Odd length read requests are always done using programmed transfer mode. */int st_dmaoddretry = 0;/* * Exabyte only: * From adb can have access to fixed vs. variable length modes. * Use 0x400 for 1k (best capacity) fixed length records. * In st_open, if minor bit 4 set then 1k records are used. * If st_exblken is set to anything other then 0 we are in fixed length mode. * Minor bit 5 requests 1K fixed-length, overriding any setting of st_exblklen. */int st_exblklen = 0;/* exabyte here for adb access, set at open time */#define EX_CT 	0x80		/* international cart - more space W/P6  */#define EX_ND	0x20		/* no disconnect  */#define EX_NBE	0x08		/* no busy enable  */#define EX_EBD	0x04		/* even byte disconnect  */#define EX_PE	0x02		/* parity enable  */#define EX_NAL	0x01		/* no auto load  */int st_exvup = (EX_CT|EX_ND|EX_NBE); /* vendor unique parameters *//* * motion and reconnect thresholds guidelines: * write operation; lower motion threshold for faster transfer *                  raise reconnect threshold for slower transfer * read operation; lower motion threshold for slower transfer *                 raise reconnect threshold for faster transfer */int st_exmotthr = 0x80;		/* motion threshold, 0x80 default */int st_exreconthr = 0xa0;	/* reconnect threshold, 0xa0 default */int st_exgapthr = 7;		/* gap threshold, 7 default */#ifdef TTIint st_extti = 0x01;		/* bitmask of unit numbers, do extra */				/* sensing so TTi display gets updated */#endifstinit(hd)	register struct hp_device *hd;{	register struct st_softc *sc = &st_softc[hd->hp_unit];	register struct buf *bp;	for (bp = sttab; bp < &sttab[NST]; bp++)		bp->b_actb = &bp->b_actf;	sc->sc_hd = hd;	sc->sc_punit = stpunit(hd->hp_flags);	sc->sc_type = stident(sc, hd);	if (sc->sc_type < 0)		return(0);	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 = &stdriver;	sc->sc_blkno = 0;	sc->sc_flags = STF_ALIVE;	return(1);}stident(sc, hd)	register struct st_softc *sc;	register struct hp_device *hd;{	int unit;	int ctlr, slave;	int i, stat, inqlen;	char idstr[32];	static int havest = 0;	struct st_inquiry {		struct	scsi_inquiry inqbuf;		struct  exb_inquiry exb_inquiry;	} st_inqbuf;	static struct scsi_fmt_cdb st_inq = {		6,		CMD_INQUIRY, 0, 0, 0, sizeof(st_inqbuf), 0	};	ctlr = hd->hp_ctlr;	slave = hd->hp_slave;	unit = sc->sc_punit;	scsi_delay(-1);	inqlen = 0x05; /* min */	st_inq.cdb[4] = 0x05;	stat = scsi_immed_command(ctlr, slave, unit, &st_inq, 				  (u_char *)&st_inqbuf, inqlen, B_READ);	/* do twice as first command on some scsi tapes always fails */	stat = scsi_immed_command(ctlr, slave, unit, &st_inq, 				  (u_char *)&st_inqbuf, inqlen, B_READ);	if (stat == -1)		goto failed;	if ((st_inqbuf.inqbuf.type != 0x01 ||  /* sequential access device */	    st_inqbuf.inqbuf.qual != 0x80 ||  /* removable media */	    (st_inqbuf.inqbuf.version != 0x01 && /* current ANSI SCSI spec */	     st_inqbuf.inqbuf.version != 0x02)) /* 0x02 is for HP DAT */	    &&	    (st_inqbuf.inqbuf.type != 0x01 ||	/* M4 ??! */	     /*	      * the M4 is a little too smart (ass?) for its own good:	      * qual codes:	      * 0x80: you can take the tape out (unit not online)	      * 0xf8: online and at 6250bpi	      * 0xf9: online and at 1600bpi	      */	     st_inqbuf.inqbuf.version != 0x09))	/* M4 tape */{printf("st: wrong specs: type %x qual %x version %d\n", st_inqbuf.inqbuf.type,st_inqbuf.inqbuf.qual, st_inqbuf.inqbuf.version);		goto failed;}	/* now get additonal info */	inqlen = 0x05 + st_inqbuf.inqbuf.len;	st_inq.cdb[4] = inqlen;	bzero(&st_inqbuf, sizeof(st_inqbuf));	stat = scsi_immed_command(ctlr, slave, unit, &st_inq, 				  (u_char *)&st_inqbuf, inqlen, B_READ);	if (st_inqbuf.inqbuf.len >= 28) {		bcopy((caddr_t)&st_inqbuf.inqbuf.vendor_id, (caddr_t)idstr, 28);		for (i = 27; i > 23; --i)			if (idstr[i] != ' ')				break;		idstr[i+1] = 0;		for (i = 23; i > 7; --i)			if (idstr[i] != ' ')				break;		idstr[i+1] = 0;		for (i = 7; i >= 0; --i)			if (idstr[i] != ' ')				break;		idstr[i+1] = 0;		printf("st%d: %s, %s rev %s\n", hd->hp_unit, idstr, &idstr[8],		       &idstr[24]);	} else if (inqlen == 5)		/* great it's a stupid device, doesn't know it's know name */		idstr[0] = idstr[8] = '\0';	else		idstr[8] = '\0';	if (stat == 0xff) { 		printf("st%d: Cant handle this tape drive\n", hd->hp_unit);		goto failed;	}	if (bcmp("EXB-8200", &idstr[8], 8) == 0) {		sc->sc_tapeid = MT_ISEXABYTE;		sc->sc_datalen[CMD_REQUEST_SENSE] = 26;		sc->sc_datalen[CMD_INQUIRY] = 52;		sc->sc_datalen[CMD_MODE_SELECT] = 17;		sc->sc_datalen[CMD_MODE_SENSE] = 17;	} else if (bcmp("VIPER 150", &idstr[8], 9) == 0) {		sc->sc_tapeid = MT_ISVIPER1;		sc->sc_datalen[CMD_REQUEST_SENSE] = 14;		sc->sc_datalen[CMD_INQUIRY] = 36;		sc->sc_datalen[CMD_MODE_SELECT] = 12;		sc->sc_datalen[CMD_MODE_SENSE] = 12;	} else if (bcmp("Python 25501", &idstr[8], 12) == 0) {		sc->sc_tapeid = MT_ISPYTHON;		sc->sc_datalen[CMD_REQUEST_SENSE] = 14;		sc->sc_datalen[CMD_INQUIRY] = 36;		sc->sc_datalen[CMD_MODE_SELECT] = 12;		sc->sc_datalen[CMD_MODE_SENSE] = 12;	} else if (bcmp("HP35450A", &idstr[8], 8) == 0) {		/* XXX "extra" stat makes the HP drive happy at boot time */		stat = scsi_test_unit_rdy(ctlr, slave, unit);		sc->sc_tapeid = MT_ISHPDAT;		sc->sc_datalen[CMD_REQUEST_SENSE] = 14;		sc->sc_datalen[CMD_INQUIRY] = 36;		sc->sc_datalen[CMD_MODE_SELECT] = 12;		sc->sc_datalen[CMD_MODE_SENSE] = 12;	} else if (bcmp("123107 SCSI", &idstr[8], 11) == 0 ||		   bcmp("OPEN REEL TAPE", &idstr[8], 14) == 0) {		sc->sc_tapeid = MT_ISMFOUR;		sc->sc_datalen[CMD_REQUEST_SENSE] = 8;		sc->sc_datalen[CMD_INQUIRY] = 5;		sc->sc_datalen[CMD_MODE_SELECT] = 12;		sc->sc_datalen[CMD_MODE_SENSE] = 12;	} else {		if (idstr[8] == '\0')			printf("st%d: No ID, assuming Archive\n", hd->hp_unit);		else			printf("st%d: Unsupported tape device\n", hd->hp_unit);		sc->sc_tapeid = MT_ISAR;		sc->sc_datalen[CMD_REQUEST_SENSE] = 8;		sc->sc_datalen[CMD_INQUIRY] = 5;		sc->sc_datalen[CMD_MODE_SELECT] = 12;		sc->sc_datalen[CMD_MODE_SENSE] = 12;	}	sc->sc_filepos = 0;		/* load xsense */	stxsense(ctlr, slave, unit, sc);	scsi_delay(0);	/* XXX if we have a tape, we must up the delays in the HA driver */	if (!havest) {		havest = 1;		scsi_delay(20000);	}	return(st_inqbuf.inqbuf.type);failed:	scsi_delay(0);	return(-1);}stopen(dev, flag, type, p)	dev_t dev;	int flag, type;	struct proc *p;{	register struct st_softc *sc = &st_softc[UNIT(dev)];	register struct st_xsense *xsense;	register int count;	register int stat;	int ctlr, slave, unit;	struct mode_select_data msd;	struct mode_sense mode;	int modlen;	int error;	static struct scsi_fmt_cdb modsel = {		6,		CMD_MODE_SELECT, 0, 0, 0, sizeof(msd), 0	};	static struct scsi_fmt_cdb modsense = {		6,		CMD_MODE_SENSE, 0, 0, 0, sizeof(mode), 0	};	ctlr = sc->sc_dq.dq_ctlr;	slave = sc->sc_dq.dq_slave;	unit = sc->sc_punit;	xsense = &st_xsense[UNIT(dev)];	if (UNIT(dev) > NST || (sc->sc_flags & STF_ALIVE) == 0)		return(ENXIO);	if (sc->sc_flags & STF_OPEN)		return(EBUSY);	/*	 * Be prepared to print error messages	 */	sc->sc_ctty = tprintf_open(p);	/* do a mode sense to get current */	modlen = sc->sc_datalen[CMD_MODE_SENSE];	modsense.cdb[4] = modlen;	stat = scsi_immed_command(ctlr, slave, unit, &modsense,				  (u_char *)&mode, modlen, B_READ);	/* do a mode sense to get current */	modlen = sc->sc_datalen[CMD_MODE_SENSE];	modsense.cdb[4] = modlen;	stat = scsi_immed_command(ctlr, slave, unit, &modsense,				  (u_char *)&mode, modlen, B_READ);	/* set record length */	switch (sc->sc_tapeid) {	case MT_ISAR:		sc->sc_blklen = 512;		break;	case MT_ISEXABYTE:		if (minor(dev) & STDEV_FIXEDBLK)			sc->sc_blklen = 0x400;		else			sc->sc_blklen = st_exblklen;		break;	case MT_ISHPDAT:		sc->sc_blklen = 512;		break;	case MT_ISVIPER1:		sc->sc_blklen = 512;		break;	case MT_ISPYTHON:		sc->sc_blklen = 512;		break;	case MT_ISMFOUR:		sc->sc_blklen = 0;		break;	default:		if ((mode.md.blklen2 << 16 |		     mode.md.blklen1 << 8 |		     mode.md.blklen0) != 0)			sc->sc_blklen = mode.md.blklen2 << 16 |					mode.md.blklen1 << 8 |					mode.md.blklen0;		else			sc->sc_blklen = 512;	}	/* setup for mode select */	msd.rsvd1 = 0;	msd.rsvd2 = 0;	msd.rsvd3 = 0;	msd.buff = 1;	msd.speed = 0;	msd.blkdeslen = 0x08;	msd.density = 0;	msd.blks2 = 0;

⌨️ 快捷键说明

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