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

📄 st.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1992 OMRON Corporation. * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * OMRON Corporation. * * 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. * *	@(#)st.c	8.2 (Berkeley) 12/6/93 *//* * st.c -- TEAC MT-2ST/N60 SCSI TAPE UNIT Device Driver * remaked by A.Fujita, MAR-22-1992 *//* * SCSI CCS (Command Command Set) disk driver. */#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/mtio.h>#include <sys/tprintf.h>#include <luna68k/dev/device.h>#include <luna68k/dev/screg.h>#include <luna68k/dev/scvar.h>extern int sc_test_unit_rdy();extern int sc_request_sense();extern int scsi_immed_command();extern char *scsi_status();extern int scgo();extern void scfree();char *sense_key();int	stinit(), ststrategy(), ststart(), stintr();struct	driver stdriver = {	stinit, "st", ststart, (int (*)()) 0, stintr, (int (*)()) 0};struct	st_softc {	struct	hp_device *sc_hd;	struct	scsi_queue sc_dq;	int	sc_flags;	short	sc_type;	/* drive type */	short	sc_punit;	/* physical unit (scsi lun) */	tpr_t	sc_ctty;} 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	0x0040u_char xsense_buff[60];struct scsi_fmt_cdb st_read_cmd  = { 6, CMD_READ  };struct scsi_fmt_cdb st_write_cmd = { 6, CMD_WRITE };struct buf sttab[NST];struct buf stbuf[NST];#define	stunit(x)	(minor(x) & 3)#define	stpunit(x)	((x) & 7)#define STDEV_NOREWIND	0x04#define	STRETRY		2	/* IO retry count */struct st_iostat {	int imax;	int imin;	int omax;	int omin;};struct st_iostat st_iostat[NST];/* * Initialize */intstinit(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_flags = STF_ALIVE;	return(1);}static struct scsi_inquiry inqbuf;static struct scsi_fmt_cdb inq = {	6,	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0};intstident(sc, hd)	struct st_softc *sc;	struct hp_device *hd;{	char idstr[32];	int unit;	register int ctlr, slave;	register int i, stat;	register int tries = 10;	ctlr = hd->hp_ctlr;	slave = hd->hp_slave;	unit = sc->sc_punit;	/*	 * See if unit exists and is a disk then read block size & nblocks.	 */	while ((stat = scsi_immed_command(ctlr, slave, unit,				  &inq, (u_char *)&inqbuf, sizeof(inqbuf))) != 0) {		if (stat < 0 || --tries < 0)			return (-1);		DELAY(1000);	}	switch (inqbuf.type) {	case 1:		/* tape */		break;	default:	/* not a disk */		printf("stident: inqbuf.type = %d\n", inqbuf.type);		return (-1);	}	bcopy((caddr_t)&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]);	return(inqbuf.type);}/* * Open */intstopen(dev, flag, type, p)	dev_t dev;	int flag, type;	struct proc *p;{	register int unit = stunit(dev);	register struct st_softc *sc = &st_softc[unit];	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;	int ctlr  = sc->sc_dq.dq_ctlr;	int slave = sc->sc_dq.dq_slave;	int stat, retry = 9;	if (unit >= NST || (sc->sc_flags & STF_ALIVE) == 0)		return(-1);	if (sc->sc_flags & STF_OPEN)		return(-1);	sc->sc_ctty = tprintf_open(p);	/* drive ready ? */	while ((stat = sc_test_unit_rdy(ctlr, slave, 0)) != 0) {		sc_request_sense(ctlr, slave, 0, sp, 8);		if (stat != STS_CHECKCOND) {			tprintf(sc->sc_ctty,				"st%d:[stopen]   %s\n", unit, scsi_status(stat));			tprintf_close(sc->sc_ctty);			return(EIO);		}		if (retry-- < 0) {			tprintf(sc->sc_ctty,				"st%d:[stopen]   %s\n", unit, sense_key(sp->key));			tprintf_close(sc->sc_ctty);			return(EIO);		}		DELAY(1000000);	}	sc->sc_flags |= STF_OPEN;	if (flag & FWRITE)		sc->sc_flags |= STF_WMODE;	sc->sc_flags &= ~STF_MOVED;	return(0);}/*ARGSUSED*/stclose(dev)	dev_t dev;{	register int unit = stunit(dev);	register struct st_softc *sc = &st_softc[unit];	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;	int ctlr  = sc->sc_hd->hp_ctlr;	int slave = sc->sc_hd->hp_slave;	int stat, retry = 9;	if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {		st_write_EOF(dev);	}	if ((minor(dev) & STDEV_NOREWIND) == 0) {		st_rewind(dev);	}	sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN);	tprintf_close(sc->sc_ctty);	return(0);}/* * Strategy */intststrategy(bp)	register struct buf *bp;{	register int unit = stunit(bp->b_dev);	register struct buf *dp = &sttab[unit];	int s;	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;		stustart(unit);	}	splx(s);}intstustart(unit)	register int unit;{	register struct st_softc *sc = &st_softc[unit];	register struct hp_device *hp = sc->sc_hd;	register struct scsi_queue *dq = &sc->sc_dq;	register struct buf *dp, *bp = sttab[unit].b_actf;	register struct scsi_fmt_cdb *cmd;	long nblks;	cmd = bp->b_flags & B_READ ? &st_read_cmd : &st_write_cmd;	cmd->cdb[1] = 1;		/* unknown setup */	if (bp->b_flags & B_READ)		sc->sc_flags &= ~STF_WRTTN;	else		sc->sc_flags |= STF_WRTTN;	nblks = bp->b_bcount >> DEV_BSHIFT;	if (bp->b_bcount % DEV_BSIZE) {		tprintf(sc->sc_ctty,			"st%d:[stustart] I/O not block aligned %d/%ld\n",			unit, DEV_BSIZE, bp->b_bcount);		bp->b_flags |= B_ERROR;		bp->b_error = EIO;				sttab[unit].b_errcnt = 0;		if (dp = bp->b_actf)			dp->b_actb = bp->b_actb;		else			sttab[unit].b_actb = bp->b_actb;		*bp->b_actb = dp;		bp->b_resid = 0;				biodone(bp);				if (sttab[unit].b_actf) {			stustart(unit);		} else {			sttab[unit].b_active = 0;		}	}	*(u_char *)(&cmd->cdb[2]) = (u_char) (nblks >> 16);	*(u_char *)(&cmd->cdb[3]) = (u_char) (nblks >>  8);	*(u_char *)(&cmd->cdb[4]) = (u_char)  nblks; 	cmd->cdb[5] = 0;		/* unknown setup */	sc->sc_flags |= STF_MOVED;	dq->dq_cdb = cmd;	dq->dq_bp  = bp;	dq->dq_flags = 0;		/* No Disconnect */	if (screq(dq))		ststart(unit);}intststart(unit)	register int unit;{	register struct st_softc *sc = &st_softc[unit];	register struct hp_device *hp = sc->sc_hd;	scstart(hp->hp_ctlr);}/* * Interrupt */char *sense_key(key)	int key;{	if (key == 0)		return("No Sense");	else if (key == 2)		return("Not Ready");	else if (key == 3)		return("Medium Error");	else if (key == 4)		return("Hardware Error");	else if (key == 5)		return("Illegal Request");	else if (key == 6)		return("Unit Attention");	else if (key == 7)		return("Data Protect");	else if (key == 8)		return("No Data");	else if (key == 11)		return("Aborted Command");	else if (key == 13)		return("Volume Overflow");	else		return("Unknown Error");}intstintr(unit, stat)	register int unit;	int stat;{	register struct st_softc *sc = &st_softc[unit];	register struct scsi_xsense *xp = (struct scsi_xsense *) xsense_buff;	register struct scsi_queue *dq = &sc->sc_dq;	register struct buf *dp, *bp = dq->dq_bp;	int ctlr  = dq->dq_ctlr;	int slave = dq->dq_slave;	if (bp->b_flags & B_READ) {		st_iostat[unit].imin = min(dq->dq_imin, st_iostat[unit].imin);		if (dq->dq_imax > st_iostat[unit].imax) {			st_iostat[unit].imax = dq->dq_imax;#ifdef ST_IOSTAT			printf("stintr: st%d  INPUT	MAX = %d, MIN = %d\n",			       unit, st_iostat[unit].imax, st_iostat[unit].imin);#endif		}	} else {		st_iostat[unit].omin = min(dq->dq_omin, st_iostat[unit].omin);		if (dq->dq_omax > st_iostat[unit].omax) {			st_iostat[unit].omax = dq->dq_omax;#ifdef ST_IOSTAT			printf("stintr: st%d  OUTPUT	MAX = %d, MIN = %d\n",			       unit, st_iostat[unit].omax, st_iostat[unit].omin);#endif		}	}	if (stat < 0) {		bp->b_flags |= B_ERROR;		bp->b_error = EIO;		goto done;	}	switch (stat) {	/* scsi command completed ok */	case 0:		bp->b_resid = 0;		break;	/* more status */	case STS_CHECKCOND:		sc_request_sense(ctlr, slave, 0, xp, 8);#ifdef DEBUG		printf("stintr: xsense_buff[0] = 0x%s\n", hexstr(xsense_buff[0], 2));		printf("stintr: xsense_buff[2] = 0x%s\n", hexstr(xsense_buff[2], 2));		printf("stintr: Sense Key = [%s]\n", sense_key(xp->key));#endif		if (xp->valid) {			bp->b_resid = (u_long)((xp->info1 << 24) |					       (xp->info2 << 16) |					       (xp->info3 << 8) |					       (xp->info4));			bp->b_resid <<= DEV_BSHIFT;		}		if (xp->filemark) {		/* End of File *//*			tprintf(sc->sc_ctty, "st%d:[stintr]   End of File\n", unit);			bp->b_flags |= B_ERROR;			bp->b_error = EIO; */			break;		}		if (xp->key) {			tprintf(sc->sc_ctty, "st%d:[stintr]   %s\n", unit, sense_key(xp->key));			bp->b_flags |= B_ERROR;			bp->b_error = EIO;			break;		}		if (xp->eom) {		/* End of TAPE */			tprintf(sc->sc_ctty, "st%d:[stintr]   End of Tape\n", unit);			bp->b_flags |= B_ERROR;			bp->b_error = ENOSPC;			break;		}		tprintf(sc->sc_ctty, "st%d:[stintr]   unknown scsi error\n", unit);		bp->b_flags |= B_ERROR;		bp->b_error = EIO;		break;	default:		tprintf(sc->sc_ctty, "st%d:[stintr]   stintr unknown stat 0x%x\n", unit, stat);		break;	}done:	sttab[unit].b_errcnt = 0;	if (dp = bp->b_actf)		dp->b_actb = bp->b_actb;	else		sttab[unit].b_actb = bp->b_actb;	*bp->b_actb = dp;	bp->b_resid = 0;	biodone(bp);	scfree(&sc->sc_dq);	if (sttab[unit].b_actf) {		stustart(unit);	} else {		sttab[unit].b_active = 0;	}}/* * RAW Device Routines */stread(dev, uio)	dev_t dev;	struct uio *uio;{	int unit = stunit(dev);	return(physio(ststrategy, &stbuf[unit], dev, B_READ, minphys, uio));}stwrite(dev, uio)	dev_t dev;	struct uio *uio;{	int unit = stunit(dev);	return(physio(ststrategy, &stbuf[unit], dev, B_WRITE, minphys, uio));}intstioctl(dev, cmd, data, flag, p)	dev_t dev;	int cmd;	caddr_t data;	int flag;	struct proc *p;{	return(ENXIO);}struct scsi_fmt_cdb st_cmd;st_rewind(dev)	dev_t dev;{	register int unit = stunit(dev);	register struct st_softc *sc = &st_softc[unit];	register struct scsi_fmt_cdb *cdb = &st_cmd;	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;	int ctlr, slave, stat;	int retry = 9;	ctlr  = sc->sc_hd->hp_ctlr;	slave = sc->sc_hd->hp_slave;	cdb->len = 6;	cdb->cdb[0] = CMD_REWIND;	cdb->cdb[1] = 1;	/* command finished soon */	cdb->cdb[2] = 0;	cdb->cdb[3] = 0;	cdb->cdb[4] = 0;	cdb->cdb[5] = 0;		/* unknown setup */ rewind:	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);	if (stat == 0) {		return(1);	} else {		tprintf(sc->sc_ctty, "st%d:[st_rewind]   rewind error\n", unit);		sc_request_sense(ctlr, slave, 0, sp, 8);		tprintf(sc->sc_ctty,			"st%d:[st_rewind]   status = 0x%x, sens key = 0x%x\n",			unit, stat, sp->key);		if (retry > 0) {			DELAY(1000000);			retry--;			goto rewind;		}		return(0);	}}st_write_EOF(dev)	dev_t dev;{	register int unit = stunit(dev);	register struct st_softc *sc = &st_softc[unit];	register struct scsi_fmt_cdb *cdb = &st_cmd;	int ctlr, slave, stat;	int marks = 1;	ctlr  = sc->sc_hd->hp_ctlr;	slave = sc->sc_hd->hp_slave;	cdb->len = 6;	cdb->cdb[0] = CMD_WRITE_FILEMARK;	cdb->cdb[1] = 0;	cdb->cdb[2] = 0;	cdb->cdb[3] = 0;	cdb->cdb[4] = marks;	cdb->cdb[5] = 0;		/* unknown setup */	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);	if (stat == 0)		return(1);	tprintf(sc->sc_ctty, "st%d:[st_write_EOF]   write EOF error\n", unit);	return(0);}/* * Dump */intstdump(dev)	dev_t dev;{}#endif

⌨️ 快捷键说明

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