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

📄 st.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#ident	"@@(#)st.c 1.1 92/07/30 SMI"#include "st.h"#if	NST > 0/* * *	SCSI Tape Driver * *//* * Copyright (C) 1988, 1989, 1990, 1991 by Sun Microsystems, Inc. *//* * the order of these defines is important */#include <scsi/scsi.h>#include <sys/file.h>#include <sys/mtio.h>#include <scsi/targets/stdef.h>#ifndef	MT_DENSITY#define	MT_DENSITY(dev)	((minor(dev) & MT_DENSITY_MASK) >> 3)#endif#ifndef STAT_BUS_RESET#define	STAT_BUS_RESET	0x8	/* Command experienced a bus reset */#define	STAT_DEV_RESET	0x10	/* Command experienced a device reset */#define	STAT_ABORTED	0x20	/* Command was aborted */#define	STAT_TIMEOUT	0x40	/* Command experienced a timeout */#endif#ifdef	OPENPROMS#define	DRIVER		st_ops#define	DNAME		devp->sd_dev->devi_name#define	DUNIT		devp->sd_dev->devi_unit#define	CNAME		devp->sd_dev->devi_parent->devi_name#define	CUNIT		devp->sd_dev->devi_parent->devi_unit#else	OPENPROMS#define	DRIVER		stdriver#define	DNAME		devp->sd_dev->md_driver->mdr_dname#define	DUNIT		devp->sd_dev->md_unit#define	CNAME		devp->sd_dev->md_driver->mdr_cname#define	CUNIT		devp->sd_dev->md_mc->mc_ctlr#endif	OPENPROMS#define	UPTR		((struct scsi_tape *)(devp)->sd_private)#define	SCBP(pkt)	((struct scsi_status *)(pkt)->pkt_scbp)#define	CDBP(pkt)	((union scsi_cdb *)(pkt)->pkt_cdbp)#define	ROUTE		(&devp->sd_address)#define	BP_PKT(bp)	((struct scsi_pkt *)bp->av_back)#define	Tgt(devp)	(devp->sd_address.a_target)#define	Lun(devp)	(devp->sd_address.a_lun)#define	IS_CLOSING(un)	((un)->un_state == ST_STATE_CLOSING || \	((un)->un_state == ST_STATE_SENSING && \		(un)->un_laststate == ST_STATE_CLOSING))#define	ASYNC_CMD	0#define	SYNC_CMD	1/* * Macros for internal coding of count for SPACE command: * * Isfmk is 1 when spacing filemarks; 0 when spacing records: * bit 24 set indicates a space filemark command. * Fmk sets the filemark bit (24) and changes a backspace * count into a positive number with the sign bit set. * Blk changes a backspace count into a positive number with * the sign bit set. * space_cnt converts backwards counts to negative numbers. */#define	Isfmk(x)	(((int)x & (1<<24)) != 0)#define	Fmk(x)		((1<<24)|(((int)x & (1<<31)) ? ((-(int)x) | (1<<31)):\			(int)x))#define	Blk(x)		(((int)x & (1<<31))? ((-(int)x) | (1<<31)): (int)x)#define	space_cnt(x)	((((int)x)&(1<<31))? (-(((int)x)&((1<<24)-1))):\			((int)x)&((1<<24)-1))/* * Debugging macros */#define	DEBUGGING	((scsi_options & SCSI_DEBUG_TGT) || stdebug > 1)#define	DEBUGGING_ALL	((scsi_options & SCSI_DEBUG_TGT) || stdebug)#define	DPRINTF		if (DEBUGGING) stprintf#define	DPRINTF_IOCTL	if (DEBUGGING || stdebug > 0) stprintf#define	DPRINTF_ALL	DPRINTF_IOCTL/* * Debugging turned on via conditional compilation switch -DST_DEBUG */#ifdef  ST_DEBUGint	st_debug = 0;#define	ST_DEBUG_CMDS   0x01#endif  ST_DEBUG/* * * Global Data Definitions * */extern struct st_drivetype st_drivetypes[];extern int st_ndrivetypes, st_retry_count, st_io_time, st_space_time;extern st_error_level;/* * * Local Static Data * */static int stdebug = 0;static int stpri = 0;struct scsi_device *stunits[ST_MAXUNIT];struct scsi_address *stsvdaddr[ST_MAXUNIT];static char *wrongtape =	"%s%d: wrong tape for writing- use DC6150 tape (or equivalent)\n";/* * Configuration Data */#ifdef	OPENPROMS/* * Device driver ops vector */int stslave(), stattach(), stopen(), stclose(), stread(), stwrite();int ststrategy(), stioctl();extern int nulldev(), nodev();struct dev_ops st_ops = {	1,	stslave,	stattach,	stopen,	stclose,	stread,	stwrite,	ststrategy,	nodev,	nulldev,	stioctl};#else	OPENPROMS/* * stdriver is used to call slave, attach routines from scsi_make_device */int stslave(), stattach(), stopen(), stclose(), stread(), stwrite();int ststrategy(), stioctl();extern int nulldev(), nodev();struct mb_driver stdriver = {	nulldev, stslave, stattach, nodev, nodev, nulldev, 0, "st", 0, 0, 0, 0};#endif	OPENPROMS/* * * Local Function Declarations * */static void ststart(), stinit(), make_st_cmd(), stintr();static void st_set_state(), sterrmsg(), stdone(), st_test_append();static int strunout(), st_determine_generic();static int stcmd();static void stprintf();/* * *	Autoconfiguration Routines * *//* * stslave is called by scsi_make_device at boot time. * Returns 1 on success; -1 on failure; 0 if kernel resources unavailable. */intstslave(devp)struct scsi_device *devp;{	int r;	/*	 * fill in our local array	 */	if (DUNIT >= ST_MAXUNIT)		return (0);	/* Save pointer to scsi_device struct allocated by scsi_make_device */	stunits[DUNIT] = devp;	/*	 * Make sure priority is the maximum of all host adapters with	 * tape devices so that spls properly block out other devices.	 */#ifdef	OPENPROMS	stpri = MAX(stpri, ipltospl(devp->sd_dev->devi_intr->int_pri));#else	stpri = MAX(stpri, pritospl(devp->sd_dev->md_intpri));#endif	OPENPROMS	r = st_findslave(devp, 0);	if (r < 0) {		/*		 * Save the address so we can scsi_add_device later		 * (in stopen) if necessary.		 */		stsvdaddr[DUNIT] = (struct scsi_address *)		    kmem_zalloc(sizeof (struct scsi_address));		if (stsvdaddr[DUNIT]) {			stunits[DUNIT] = 0;			*stsvdaddr[DUNIT] = devp->sd_address;		} else {			r = 0;		}	}	return (r);}/* * st_findslave is normally called by stslave, but may be called by stopen. * Returns 1 on success; -1 on failure; 0 if kernel resources unavailable. * Allocate buffers and initialize data structures. */static intst_findslave(devp, canwait)register struct scsi_device *devp;int canwait;{	struct scsi_pkt *rqpkt;	struct scsi_tape *un;	auto int (*f)() = (canwait == 0)? NULL_FUNC: SLEEP_FUNC;	int rval = -1;	/*	 * Call the routine scsi_slave to do some of the dirty work.	 * All scsi_slave does is do a TEST UNIT READY (and possibly	 * a non-extended REQUEST SENSE or two), and an INQUIRY command.	 * If the INQUIRY command succeeds, the field sd_inq in the	 * device structure will be filled in.	 *	 */	switch (scsi_slave(devp, canwait)) {	default:	case SCSIPROBE_NONCCS:		/*		 * If it returns as NON-CCS- we may have a tape drive		 * that is so busy it cannot return INQUIRY data, hence		 * we'll hang on to the driver node so that a later		 * MUNIX-style autoconfiguration will spot it and attempt		 * to open the drive again...		 */		rval = 0;		/* FALLTHROUGH */	case SCSIPROBE_NOMEM:	case SCSIPROBE_NORESP:	case SCSIPROBE_FAILURE:		if (devp->sd_inq) {			IOPBFREE (devp->sd_inq, SUN_INQSIZE);			devp->sd_inq = (struct scsi_inquiry *) 0;		}		return (rval);	case SCSIPROBE_EXISTS:		if (devp->sd_inq->inq_dtype != DTYPE_SEQUENTIAL) {			IOPBFREE (devp->sd_inq, SUN_INQSIZE);			devp->sd_inq = (struct scsi_inquiry *) 0;			return (rval);		}		break;	}	rval = 0;	/* Allocate request sense buffer. */	rqpkt = get_pktiopb(ROUTE, (caddr_t *)&devp->sd_sense, CDB_GROUP0,			1, SENSE_LENGTH, B_READ, f);	if (!rqpkt) {		return (rval);	}	makecom_g0(rqpkt, devp, FLAG_NOPARITY,	    SCMD_REQUEST_SENSE, 0, SENSE_LENGTH);	rqpkt->pkt_pmon = -1;	/*	 * The actual unit is present.	 * Now is the time to fill in the rest of our info..	 */	un = UPTR =		(struct scsi_tape *) kmem_zalloc(sizeof (struct scsi_tape));	if (!un) {		printf("%s%d: no memory for tape structure\n", DNAME, DUNIT);		free_pktiopb(rqpkt, (caddr_t)devp->sd_sense, SENSE_LENGTH);		return (rval);	}	un->un_rbufp = (struct buf *) kmem_zalloc(sizeof (struct buf));	un->un_sbufp = (struct buf *) kmem_zalloc(sizeof (struct buf));	/* IOPBALLOC guarantees longword aligned allocation from iopbmap */	un->un_mspl = (struct seq_mode *) IOPBALLOC(MSIZE);	if (!un->un_rbufp || !un->un_sbufp || !un->un_mspl) {		printf("%s%d: no memory for raw/special buffer\n",			DNAME, DUNIT);		if (un->un_rbufp)			(void) kmem_free((caddr_t)un->un_rbufp,				sizeof (struct buf));		if (un->un_sbufp)			(void) kmem_free((caddr_t)un->un_rbufp,				sizeof (struct buf));		if (un->un_mspl) {			IOPBFREE(un->un_mspl, MSIZE);		}		(void) kmem_free((caddr_t) un, sizeof (struct scsi_tape));		free_pktiopb(rqpkt, (caddr_t)devp->sd_sense, SENSE_LENGTH);		return (rval);	} else {		rval = 1;	}	devp->sd_present = 1;	un->un_fileno = -1;	rqpkt->pkt_time = st_io_time;	rqpkt->pkt_comp = stintr;	un->un_rqs = rqpkt;	un->un_sd = devp;	un->un_dev = DUNIT;#ifdef	OPENPROMS	devp->sd_dev->devi_driver = &st_ops;#else	devp->sd_dev->md_dk = (short) -1;#endif	OPENPROMS	return (rval);}/* * Attach tape. The controller is there. * Called by scsi_make_device. * Attach device (boot time or load time, if loadable module). * Also called by stopen. */intstattach(devp)struct scsi_device *devp;{	struct st_drivetype *dp;	struct scsi_tape *un = UPTR;	auto int found = 0;	/*	 * Determine type of tape controller.  Type is determined by	 * checking the resulta of the earlier inquiry command and	 * comparing vendor ids with strings in a table declared in stdef.h.	 */	for (dp = st_drivetypes; dp < &st_drivetypes[st_ndrivetypes]; dp++) {		if (dp->length == 0)			continue;		if (bcmp(devp->sd_inq->inq_vid,  dp->vid, dp->length) == 0) {			found = 1;			break;		}	}	if (!found) {		found = (sizeof (struct st_drivetype)) + 44;		dp = (struct st_drivetype *) kmem_zalloc((unsigned) found);		if (!dp) {			return;		}		dp->name = (caddr_t) ((u_long) dp + sizeof (*dp));		/*		 * Make up a name		 */		bcopy("Vendor '", dp->name, 8);		bcopy((caddr_t) devp->sd_inq->inq_vid, &dp->name[8], 8);		bcopy("' Product '", &dp->name[16], 11);		bcopy((caddr_t) devp->sd_inq->inq_pid, &dp->name[27], 16);		dp->name[43] = '\'';		/*		 * 'clean' vendor and product strings of non-printing chars		 */		for (found = 0; found < 43; found++) {			if (dp->name[found] < 040 || dp->name[found] > 0176)				dp->name[found] = '.';		}	}	/* Store tape drive characteristics. */	un->un_dp = dp;	un->un_status = 0;	un->un_attached = 1;	if ((dp->options & ST_NOPARITY) == 0)		un->un_rqs->pkt_flags &= ~FLAG_NOPARITY;	printf("%s%d: <%s>\n", DNAME, DUNIT, dp->name);}/* * * * Regular Unix Entry points * * */intstopen(dev, flag)dev_t dev;int flag;{	int s, unit, err;	u_int resid;	register struct scsi_device *devp;	register struct scsi_tape *un;	/*	 * validate that we are addressing a sensible unit	 */	unit = MTUNIT(dev);	if (DEBUGGING_ALL) {		printf("st%d:\tstopen dev 0x%x flag 0x%x\n", unit, dev, flag);	}	if (unit >= ST_MAXUNIT) {		return (ENXIO);	}	if (!(devp = stunits[unit])) {		struct scsi_address *sa = stsvdaddr[unit];		if (sa) {			if (scsi_add_device(sa, &DRIVER, "st", unit) == 0) {				return (ENXIO);			}			/* stslave will have stuffed stunits */			devp = stunits[unit];			(void) kmem_free((caddr_t) sa, sizeof (*sa));			stsvdaddr[unit] = (struct scsi_address *) 0;		} else {			return (ENXIO);		}	}	if (!devp->sd_present || (!(un = UPTR))) {		/*		 *  If findslave succeeds, we'll get a valid UPTR...		 */		s = splr(stpri);		if (st_findslave(devp, 1) <= 0) {			(void) splx(s);			return (ENXIO);		}		(void) splx(s);		un = UPTR;#ifdef	OPENPROMS		printf("%s%d at %s%d target %d lun %d\n", DNAME, DUNIT,				CNAME, CUNIT, Tgt(devp), Lun(devp));#else	OPENPROMS		printf("%s%d at %s%d slave %d\n", DNAME, DUNIT,				CNAME, CUNIT, Tgt(devp)<<3|Lun(devp));#endif	OPENPROMS	}	if (!un->un_attached) {		s = splr(stpri);		stattach(devp);		(void) splx(s);		if (!un->un_attached)			return (ENXIO);	}	/*	 * Check for the case of the tape in the middle of closing.	 * This isn't simply a check of the current state, because	 * we could be in state of sensing with the previous state	 * that of closing.	 */	s = splr(stpri);	if (IS_CLOSING(un)) {		while (IS_CLOSING(un)) {			if (sleep((caddr_t) &lbolt, (PZERO+1)|PCATCH)) {				(void) splx(s);				return (EINTR);			}		}	} else if (un->un_state != ST_STATE_CLOSED) {		(void) splx(s);		return (EBUSY);	}	(void) splx(s);	/*	 * record current dev	 */	un->un_dev = dev;	/*	 * See whether this is a generic device that we haven't figured	 * anything out about yet.	 */	if (un->un_dp->type == ST_TYPE_INVALID) {		if (st_determine_generic(devp))			return (EIO);	}	/*	 * Clean up after any errors left by 'last' close.	 * This also handles the case of the initial open.	 */	un->un_laststate = un->un_state;	un->un_state = ST_STATE_OPENING;	resid = un->un_err_resid;	/* save resid for status reporting */	err = stcmd(devp, SCMD_TEST_UNIT_READY, 0, SYNC_CMD);	un->un_err_resid = resid;	/* restore resid */	if (err != 0) {		if (err == EINTR) {			un->un_laststate = un->un_state;			un->un_state = ST_STATE_CLOSED;			return (err);		}		/*		 * Make sure the tape is ready		 */		un->un_fileno = -1;		if (un->un_status != KEY_UNIT_ATTENTION) {			un->un_laststate = un->un_state;			un->un_state = ST_STATE_CLOSED;			return (EIO);		}	}	resid = un->un_err_resid;	/* save resid for status reporting */	if (un->un_fileno < 0 && st_loadtape(devp)) {		un->un_err_resid = resid;	/* restore resid */		un->un_laststate = un->un_state;		un->un_state = ST_STATE_CLOSED;		return (EIO);	}	/*	 * do a mode sense to pick up state of current write-protect,	 */	(void) stcmd(devp, SCMD_MODE_SENSE, MSIZE, SYNC_CMD);

⌨️ 快捷键说明

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